• Java ----- 线程(Thread)(二)创建线程


    Java程序中的 public static void main()  方法时主线程的入口,当运行Java程序时,会先执行这个方法。

    程序运行的时候系统(cpu)会分配一个进程用于执行该程序,在Java中,即使在运行的程序中没有创建线程,后台也会有多个线程运行,如主线程、gc 线程,其中主线程为main函数是程序入口,用于执行整个程序,gc 为jvm 的垃圾回收机制,他们是相互独立的执行路径,当开辟了多个线程时,线程的运行由调度器进行安排调度,线程的先后顺序是不能人为干预的,因为调度器是操作系统的cpu进行调度,因此线程会增加额外的开销,可以通过并发进行控制开销。并发还有个好处是,可以避免在对同一份资源进行操作时,存在的资源抢夺问题,在每个线程在自己的工作内交互时,内存控制不当会造成数据不一致。

    注意:

    (1)、每个程序至少自动拥有一个线程,称为主线程。

    (2)、当程序加载到内存时启动主线程。

    (3)、开发中用户编写的线程一般是指除了主线程之外的其他线程,主线程调用start()方法,子线程执行run 方法,多条执行路径,主线程与子线程交替执行。

    使用一个线程的主要步骤:

    (1)、定义一个线程,同时指明这个线程索要执行的代码,即期望完成的功能

    (2)、创建线程对象

    (3)、启动线程

    (4)、终止线程

    Thread 类常用的方法:

    java 提供了java.lang.Thread 类支持多线程编程,该类提供了大量的方法来控制和操作线程,如下

    定义一个线程类常见的两种方法:继承java.lang.Thread 类和实现java.lang.Runnable 接口

    1、使用Thread 类创建线程

    创建线程时继承Thread 类并重写Thread类的run 方法。Thread 类的run 方法是线程要执行操作任务的方法,所以线程要执行的操作代码都需要写在run() 方法中,并通过调用start() 方法来启动线程。

    使用继承Thread 类的方式创建线程主要步骤 

    (1)、定义一个类继承Thread 类,重写run 方法,

    (2)、重写run 方法,并在方法中写需要输出的数据

    (3)、创建线程对象

    (4)、调用start() 方法启动线程

     注意:创建对象时不会执行线程,必须调用线程对象的start() 方法才会使线程开始运行。

    package com.obge.threadstu;
    
    public class ThreadStu extends Thread {
    
        private int icount =0;
        //重写run 方法
        public void run(){
    //        while(icount <5){
    //            icount ++;
    //            System.out.println("while的值:"+icount);
    //        }
    
            do{
                icount ++;
                System.out.println("do_while的值:"+icount);
            }while (icount<4);
    
    //        for(;icount<3;icount++){
    //            System.out.println("for的值:"+icount);
    //        }
    
    
        }
    
    }
    
    
    
    package com.obge.threadstu;
    
    public class TestThread {
        public static void main(String[] args) {
            //实例化线程对象
            ThreadStu threadStu = new ThreadStu();
            threadStu.start();
        }
    
    
    }

    缺点:虽然,使用继承Thread的方式简单明了,但是如果定义的类已经继承了其他类则无法在继承Thread 类。所以引入了另一种方式实现Runnable 接口创建线程

    在来一个小例子:借助线程从网络中下载文件

    2、使用Runnable 接口创建线程

    Runnable 接口中声明了一个run()方法(即public void run() )

    一个类可以通过实现Runnable 接口并实现其 run() 方法完成线程的所有活动,其中以实现的run() 方法称为该对象的线程体。任何实现Runnable 接口的对象都可以作为一个线程的目标对象。

    使用实现Runnable 接口方式创建对象的主要步骤:

    (1)、定义一个类实现java.lang.Runnable 接口

    (2)、实现该接口的run()方法,并在方法中写需要输出的数据

    (3)、创建线程对象

    (4)、调用start() 方法启动线程

    使借助Thread thread = new Thread( new RunnableStu());创建对象

    package com.obge.threadstu;
    
    public class RunnableStu implements Runnable{
        //重写注解  一个内建注解
        @Override
        public void run() {
            for(int i = 0;i<3;i++){
                System.out.println("for的值:"+i);
            }
    
        }
    }
    
    package com.obge.threadstu;
    
    public class TestThread {
        public static void main(String[] args) {
            //实例化线程对象
            //ThreadStu threadStu = new ThreadStu();
            Thread thread = new Thread( new RunnableStu());
            thread.start();
        }
    
    
    }

     另一个小例子

    两种方式比较:

    直接继承Thread 类的方式编写简单,可以直接操作线程,适合单重继承的情况

    实现Runnable接口方式,当一个线程继承另一个类时,只能实现Runnable 接口的方法创建线程,使多个线程之间使用同一个Runnable对象(因为java 只能单继承,可以实现多个接口)

    3、实现Callable 接口

    主要步骤:

    (1)、实现Callable 接口,需要返回值类型

    (2)、重写call 方法 ,需要抛出异常

    (3)、创建目标对象

    (4)、创建执行服务 :ExecutorService executorService = Executors.newFixedThreadPool();

    (5)、提交执行:Future<Boolean> result1 = executorService.submit(thread1);

    (6)、获取结果:boolean r1 = result1.get();

    (7)、关闭服务:executorService.shutdown();

    package com.obge.threadstu;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    /*
     * Callable 可以抛出异常也可以定义返回值
     */
    public class CallableStu implements Callable<Boolean>{
        //声明创建变量
        private String url;
        private String name;
        //提供构造方法,用于对象创建,对类进行初始化
        public CallableStu(String url,String name) {
            this.url = url;
            this.name = name;
        }
        //通过实现Callable 方式,创建线程
        @Override
        public Boolean call() throws Exception {
            WebDownloader webDownloader = new WebDownloader();
            webDownloader.downloads(url, name);
            System.out.println("下载图片的名字:"+name);
            return true;
        }    
        //程序入口
        public static void main(String[] args) throws InterruptedException, ExecutionException {        
            //实例化线程
            CallableStu thread1 = new CallableStu("https://img.alicdn.com/imgextra/i4/121853076/O1CN01kOYLk81Yaqvw2jDOc_!!0-saturn_solar.jpg_468x468q75.jpg_.webp","img1.jpg");
            CallableStu thread2 = new CallableStu("https://mirrors.bfsu.edu.cn/apache//commons/io/binaries/commons-io-2.8.0-bin.zip","file1.jpg");
            CallableStu thread3 = new CallableStu("https://img.alicdn.com/imgextra/i4/15012183/O1CN01yDHHYJ1RzrGb2Up4z_!!0-saturn_solar.jpg_468x468q75.jpg_.webp","img2.jpg");
            CallableStu thread4 = new CallableStu("https://img.alicdn.com/imgextra/i3/127372649/O1CN01dadNEf1VRHpmz7f66_!!0-saturn_solar.jpg_468x468q75.jpg_.webp","img3.jpg");
            //线程执行,其顺序由不能控制
            
            //创建执行服务,将四个线程放到池子里
            ExecutorService executorService = Executors.newFixedThreadPool(4);
            //提交执行
            Future<Boolean> result1 = executorService.submit(thread1);
            Future<Boolean> result2 = executorService.submit(thread2);
            Future<Boolean> result3 = executorService.submit(thread3);
            Future<Boolean> result4 = executorService.submit(thread4);
            //获取结果    
            boolean r1 = result1.get();
            boolean r2 = result2.get();
            boolean r3 = result3.get();
            boolean r4 = result4.get();
            System.out.println("打印结果为:r1="+r1+",r2="+r2+",r3="+r3+",r4="+r4);
            //关闭服务
            executorService.shutdown();
        }
    
    }

    下载类

    package com.obge.threadstu;
    
    import java.io.File;
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.net.URL;
    
    import org.apache.commons.io.FileUtils;
    //下载类
    public class WebDownloader {
        //下载方法
        public void downloads(String url,String name) {        
            try {
                FileUtils.copyURLToFile(new URL(url),new File(name));
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
  • 相关阅读:
    POJ 3263 Tallest Cow(线段树)
    面试题54——表示数值的字符串
    ORA-01555错误总结(二)
    《AndroidStudio每日一贴》11. 重构之提炼为常量
    机器学习系统构建
    jsp不通过form和Ajax提交
    南邮算法分析与设计实验2 动态规划法
    cocos2d-x 3.2 之 2048 —— 第五篇
    Cocos2d-x学习资源集锦+有奖抽楼活动
    VMware虚拟机无法识别U盘解决方式
  • 原文地址:https://www.cnblogs.com/obge/p/13636383.html
Copyright © 2020-2023  润新知