结合多本著作和个人开发经验,整理Java多线程入门手册( 三 )

  • 可以通过 FutureTask 对象的get方法获取线程的运算结果
  • 案例:还是计算10以内的偶数,这一次将计算结果返回,因为有多个数据所以返回数据用集合存储,则Callable接口的泛型类型应该是集合
    实现类:
     import java.util.ArrayList;import java.util.List;import java.util.concurrent.Callable;// 1、实现Callable,指明泛型类型public class CallableImpl implements Callable<List<Integer>> {// 2、线程返回Integer类型数据,抛出异常@Overridepublic List<Integer> call() throws Exception {List<Integer> list = new ArrayList<>();for (int i = 0; i < 10; i++) {if (i % 2 == 0){// 3、偶数存储到集合中list.add(i);}}// 4、返回集合return list;}}测试类:
     import java.util.List;import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;public class CallableMain {public static void main(String[] args) {// 1、创建Callable实现类对象CallableImpl callable = new CallableImpl();// 2、创建 FutureTask对象传入 callable// FutureTask 实现 了 RunnableFuture,RunnableFuture实现了Runnable接口和Future接口FutureTask<List<Integer>> task = new FutureTask<>(callable);// 3、将 task 传入线程对象Thread t1 = new Thread(task);// 4、启动线程t1.start();// 5、获取线程返回数据try {List<Integer> list = task.get();System.out.println(list);} catch (Exception e) {e.printStackTrace();}}}三种实现方式区别
    • Java单继承的特性决定,使用实现接口的方式创建线程更灵活
    • Callable实现call方法有返回值和异常抛出,方便定位问题,配合FutureTask可以获取线程运算结果,而run方法没有返回值,没有异常抛出
    • 如果线程运行结束后不需要返回值,则推荐使用实现Runnable接口方式
    小贴士:有不少文章中写到【实现的方式更适合用来处理多个线程有共享数据的情况】,很多小伙伴也拿去背,这句话怎么看都不对吧,多线程共享数据不加锁,不同步怎么着也不能避免线程安全问题!
    线程开辟
    • 开辟线程需要通过Thread类创建对象
    • 启动线程需要Thread对象调用start方法
    • 线程的功能可以装在Thread类的run方法或者Runnable接口实现类的run方法类中
    • 线程开辟需要在另一个线程中开启,新开辟的线程称为子线程

    结合多本著作和个人开发经验,整理Java多线程入门手册

    文章插图
    小贴士:对于Java应用程序java.exe来讲,至少会存在三个线程:
    main主线程
    gc垃圾回收线程
    异常处理线程,如果发生异常会影响主线程 。
    线程状态线程的状态网上有 5种状态 和 6种状态 两个版本
    五种状态版本:是基于现代操作系统线程状态角度解释的
    新建:当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态
    就绪:处于新建状态的线程被start后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件,只是没分配到CPU资源
    运行:当就绪的线程被调度并获得CPU资源时,便进入运行状态,run方法定义了线程的操作和功能
    阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出CPU并临时终止自己的执行,进入阻塞状态
    死亡:线程完成了它的全部工作或线程被提前强制性地中止或出现异常导致结束
    在JDK5的时候Thread类中定义了一个State枚举类,其中定义了6种线程状态,这是Java官方定义的Java线程的6种状态
    结合多本著作和个人开发经验,整理Java多线程入门手册

    文章插图
    1)NEW:处于NEW状态的线程此时尚未启动 。只是通过new Thread()创建了线程对象,并未调用start()方法
    2)RUNNABLE:Java线程的 RUNNABLE 状态其实是包括了传统操作系统线程的 就绪(ready) 和 运行(running) 两个状态的 。处于 RUNNABLE 状态的线程可能在 Java 虚拟机中运行,也有可能在等待 CPU 分配资源
    3)BLOCKED:阻塞状态 。处于 BLOCKED 状态的线程正等待锁的释放以进入同步区,就好比你去食堂打饭,只有一个窗口你就得排队,等前边的人结束之后你完成打饭
    4)WAITING :等待状态 。处于等待状态的线程变成 RUNNABLE 状态需要其他线程唤醒
    可以通过调用一下三个方法进入等待状态:


    推荐阅读