• java核心学习(二十一) 多线程---创建启动线程的三种方式


       本节开始java多线程编程的学习,对于操作系统、进程、线程的基本概念不再赘述,只是了解java对于多线程编程的支持有哪些。

    一、继承Thread类来创建线程

       java语言中使用Thread类来代表线程,代表线程的类可以通过继承Thread类并重写run()方法来实现多线程开发,调用线程类实例的start方法来启动该线程。下面来试一试

     

    package ThreadTest;
    
    public class FirstThread extends Thread{
        private int i;
        public void run(){
            for(;i<100;i++){
                System.out.println(getName() + " "+i);
            }
        }
        public static void main(String[] args){
            for(int i = 0; i<10000 ; i++){
                //Thread.currentThread()方法,获取当前线程实例
                System.out.println(Thread.currentThread().getName() + " " +i);
                if(i == 20){
                    new FirstThread().start();
                    new FirstThread().start();
                }
            }
        }
    }

        输出结果可想而知,三个线程交替运行。其中mian线程是Thread-0 和 Thread-1的父亲线程,使用继承Thread类的线程类来创建线程时,多个线程无法共享线程类的实例变量。

    二、实现Runnable接口来创建线程类

      Runnable接口中只有一个抽象方法 void run(),是一个函数式接口。如果打开Thread类的代码,就可以发现Thread类也是实现了Runnable接口。

      实现Runnable接口的run()方法的类只能算一个target,只是为线程提供了run方法,要真正创建线程必须调用Thread的构造方法来创建Thread,其实也是使用了Thread来创建线程。

      下面来试一试

    package ThreadTest;
    
    public class SecondThread implements Runnable{
        private int i;
        public void run(){
            for(;i<100;i++){
                System.out.println(Thread.currentThread().getName()+ " " +i);
            }
        }
        public static void main(String[] args)
        {
            for(int i = 0;i<100;i++){
                
                System.out.println(Thread.currentThread().getName()+ " "+ i);
                if(i==20){
                    Runnable st = new SecondThread();
                    new Thread(st,"自定义名字").start();
                }
            }
        }
    }

      

        这是Thread的run方法,可以看到Thread调用了Runnable实现类的run方法。

     三、使用Callable 和 Future创建线程

      Callable接口只有一个call()抽象方法,与run()不同的是call()有返回值,可以抛出异常

      下图是Callable接口定义

      

      泛型V代表了call方法的返回值类型

      那么如何把实现了Callable接口的类的call方法当做线程执行体呢,如何获取call方法的返回值呢?

      这需要用到Future,Future接口代表call()方法的返回值,调用Future实例的get方法可以去的返回值,对应于Callable接口,Future也支持泛型。

      还需要用到FutureTask类,这个类实现了Future接口和Runnable,可以获取到返回值,也可以作为线程创建的target

      FutureTask的构造器

       FutureTask的run方法

     

       下面用一下

    package ThreadTest;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.Future;
    import java.util.concurrent.FutureTask;
    
    public class ThirdThread{
        public static void main(String[] args){
            ThirdThread tt = new ThirdThread();
            FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    int i =0;
                    for(;i<100;i++){
                        System.out.println(Thread.currentThread().getName() + " " + i);
                    }
                    return i;
                }
            });
            for (int i = 0;i<100;i++){
                System.out.println(Thread.currentThread().getName()+" "+i);
                if(i == 20){
                    new Thread(task,"带返回值的线程").start();
                }
                try {
                    System.out.println("子线程返回值:" + task.get());
                }catch (Exception ex){
                    ex.printStackTrace();
                }
            }
        }
    }

        这里要注意,调用FutureTask方法的get方法时,当前线程在取得返回值之前会被阻塞。

        通常使用后两种方式来创建线程

  • 相关阅读:
    paip.提升效率僵尸代码的迷思
    paip.输入法编程词库多意义条目分割 python实现.
    paip.提升效率提升绑定层次form绑定取代field绑定
    paip.提升效率调试日志系统日志参数含义python
    paip.自定义java 泛型类与泛型方法的实现总结
    paip.提升效率request自动绑定domain object
    paip.提升效率filter map reduce 的java 函数式编程实现
    paip.php 5.0 5.3 5.4 5.5 6.0的新特性总结与比较
    paip.解决中文url路径的问题图片文件不能显示
    paip.判断字符是否中文与以及判读是否是汉字uapi python java php
  • 原文地址:https://www.cnblogs.com/Theshy/p/7574393.html
Copyright © 2020-2023  润新知