zoukankan      html  css  js  c++  java
  • Java 创建线程的三种方式

    在java中,目前创建线程的一共有三种形式:

        1. 使用Thread类创建线程

        2. 使用Runnable接口创建线程

        3. 使用Callable接口和Future类创建线程

    使用Thread类创建线程:

       使用Thread类创建线程是三种方法里面最简单的,因为直接继承了Thread类,当继承Thread类创建了一个对象,这个对象便是线程对象

    class FristThread extends Thread{     //继承Thread类
        private int i;
        public FristThread(int i){
            this.i = i;
        }
        public void run(){               //重写Run方法,并编写线程执行体
            for(;i<100;i++){
                System.out.println(this.getName() +" "+ i);
            }
        }
    }
    public class Threads{
        public static void main(String[] args){
            for(int i=0;i<100;i++){
                System.out.println(Thread.currentThread().getName()+" "+i);
                if(i == 20){
                    new FristThread(i).start();  //创建线程并调用
                    new FristThread(i).start();
                }
            }
        }
    }

    使用Runnable接口创建线程:

     使用Runnable接口创建线程,比使用Thread类创建线程要复杂一些。步骤如下:

      1. 定义Runnable接口实现类,并重写run方法,该方法内放入线程执行体

      2. 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象

     说简单点,继承Runnable接口实现类只是编写线程执行程序(线程执行体),并将线程执行程序赋值到Thread对象的run方法,真正线程对象依然是Thread类(或是继承Thread实现类)的实例,

    class SecondeThread implements Runnable{     //Runnable接口实现类
    
        private int i;
        @Override
        public void run() {
            // TODO Auto-generated method stub
            for(;i<100;i++){
                System.out.println(Thread.currentThread() +" "+ i);
            }
        }
    }
    public class Threads{
        public static void main(String[] args){
            for(int i=0;i<100;i++){
                System.out.println(Thread.currentThread().getName()+" "+i);
                if(i == 40){
                    SecondeThread st = new SecondeThread();  //创建实现类的实例
                    new Thread(st).start();                  //创建线程,调用实现类的实例,并运行
                    new Thread(st).start();                  
                }
            }
        }
    } 

    使用Callable接口和Future接口创建线程:

     使用Callable接口和Future类创建线程是三种方法中创建线程最复杂,步骤如下:

      1.创建Callable接口的实现类,并重写call()方法,该call()方法作为线程执行体,可以有返回值,可以声明抛出异常,Java 8开始可以直接使用Lambda表达式创建Callable对象

      2.使用FutureTask类来包装Callable对象,FutureTask类继承了Future接口以及Runnable接口,Future接口用于获取Callable接口call()方法的返回值

      3.使用FutureTask对象作为Thread的target创建并启动线程,一个FutureTask对象只能创建一个线程

      4.使用FutureTask对象的get()方法获取子线程执行结束后的返回值

    class ThirdThread implements Callable{
    
        private int i;
        @Override
        public Object call() throws Exception {
            // TODO Auto-generated method stub
            for(;i<100;i++){
                System.out.println(Thread.currentThread() +" "+ i);
            }
            return i;
        }
        
    }
    public class Threads{
        public static void main(String[] args){
            for(int i=0;i<100;i++){
                System.out.println(Thread.currentThread().getName()+" "+i);
                if(i == 60){
                    ThirdThread tt = new ThirdThread();
                    FutureTask<Integer> task = new FutureTask<Integer>(tt);
    //                FutureTask<Integer> task1 = new FutureTask<Integer>(tt);
                    new Thread(task,"有返回值的线程1").start();
                    new Thread(task,"有返回值的线程2").start();
                    try {
                        System.out.println("子线程返回值:"+task.get());
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    总结:

    为什么会有三种创建线程的方式,原因如下:

        1.类只能继承一个父类,但可以继承多个接口。如果一个类要继承一个父类,那么就不能继承Thread类来创建线程,因此有了实现继承接口来创建线程,这就是1与2和3的区别。

        2.方法2 和方法3都是继承接口的形式来创建线程,区别在于,方法二是重写了Run方法,没有返回值,而方法三是重写了call方法,是有返回值的,只是返回值需要线程执行体执行完后才返回。

        鉴于上面分析:若要创建线程,最好采用继承Runnale或者Callable接口形式会更好一些。

    PS  完整代码:

    /**
     * 线程
     * */
    class FristThread extends Thread{
        private int i;
        public FristThread(int i){
            this.i = i;
        }
        public void run(){
            for(;i<100;i++){
                System.out.println(this.getName() +" "+ i);
            }
        }
    }
    class SecondeThread implements Runnable{
    
        private int i;
        @Override
        public void run() {
            // TODO Auto-generated method stub
            for(;i<100;i++){
                System.out.println(Thread.currentThread() +" "+ i);
            }
        }
    }
    
    class ThirdThread implements Callable{
    
        private int i;
        @Override
        public Object call() throws Exception {
            // TODO Auto-generated method stub
            for(;i<100;i++){
                System.out.println(Thread.currentThread() +" "+ i);
            }
            return i;
        }
        
    }
    public class Threads{
        public static void main(String[] args){
            for(int i=0;i<100;i++){
                System.out.println(Thread.currentThread().getName()+" "+i);
                if(i == 20){
                    new FristThread(i).start();
                    new FristThread(i).start();
                }else if(i == 40){
                    SecondeThread st = new SecondeThread();
                    new Thread(st).start();
                    new Thread(st).start();
                }else if(i == 60){
                    ThirdThread tt = new ThirdThread();
                    FutureTask<Integer> task = new FutureTask<Integer>(tt);
    //                FutureTask<Integer> task1 = new FutureTask<Integer>(tt);
                    new Thread(task,"有返回值的线程1").start();
                    new Thread(task,"有返回值的线程2").start();
                    try {
                        System.out.println("子线程返回值:"+task.get());
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    View Code
  • 相关阅读:
    竞赛入门经典 3.2竖式问题
    竞赛入门经典 3-4竖式
    hdu 3547 (polya定理 + 小高精)
    浅入 dancing links x(舞蹈链算法)
    计算阶乘的另一些有趣的算法(转载)
    莫比乌斯反演
    STL的常用用法、函数汇总(不定时更新)
    博弈论的总结
    14年安徽省赛数论题etc.
    CCF 第六次计算机职业认证 第四题 收货 stl动态存储和fleury算法的综合应用
  • 原文地址:https://www.cnblogs.com/hjlin/p/11381943.html
Copyright © 2011-2022 走看看