欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

荐 【Java】--创建线程方法之Callable

程序员文章站 2022-05-07 18:17:15
在Java基础部分我们知道,创建线程的两种方式:继承Thread类实现Runable接口简单对比:与Runable相比继承Thread使用简单;但由于Java是单继承,不能再继承其他类,扩展性较差从JDK1.5开始java.util.concurrent包下,新增了Callable接口,可以通过实现Callable接口创建线程。与Runable接口对比实现Runable接口需重写run方法,而实现Callable是重写Call方法run方法无返回值、不能抛异常call方法有返回值...

简介

Java基础部分我们知道,创建线程的两种方式:

  • 继承Thread类
  • 实现Runable接口

简单对比:

与Runable相比继承Thread使用简单;但由于Java是单继承,不能再继承其他类,扩展性较差

从JDK1.5开始java.util.concurrent包下,新增了Callable接口,可以通过实现Callable接口创建线程。

与Runable接口对比
实现Runable接口需重写run方法,而实现Callable是重写Call方法
run方法无返回值、不能抛异常
call方法有返回值、可以抛异常,相当于加强版Runable接口

Callable使用

Callable如何使用呢?

根据已知,推到未知

已知:

  1. 创建线程都是通过Thread类
  2. Thread的构造方法不能接收Callable接口
  3. Thread的构造方法能接收Runable接口

未知:
于是我们就需要这样一个类,它能接收Callable接口同时实现了Runable接口
这个类就是:FutureTask

  • FutureTask实现了Runnable接口
public class FutureTask<V> implements RunnableFuture<V>

荐
                                                        【Java】--创建线程方法之Callable

  • FutureTask能接收Callable接口
	public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

简单使用

public class CallableDemo {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();

        FutureTask<Integer> futureTask = new FutureTask<>(myThread);

        Thread t1 = new Thread(futureTask,"t1");
        t1.start();

    }
}
class MyThread implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        System.out.println("**********call**********");
        return 1024;
    }
}

Callable VS Runable

已经有Runable(JDK1.0)接口了,为什么在JDK1.5又提供了Callable 接口?

通过上面的简单使用可以发现两处不同:

  1. 有返回值
public class CallableDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyThread myThread = new MyThread();

        FutureTask<Integer> futureTask = new FutureTask<>(myThread);

        Thread t1 = new Thread(futureTask,"t1");
        t1.start();

        int result1 = 100;
        int result2 = futureTask.get();
        System.out.println("result:"+(result1+result2));

    }
}
class MyThread implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        System.out.println("**********call**********");
        return 1024;
    }
}

荐
                                                        【Java】--创建线程方法之Callable

注意:
通过FutureTask类提供的get()方法获取返回值时,如果没有计算完成就去强求会导致阻塞,因此应放在最后
分支合并:
无需等待某些计算复杂的线程,可以继续执行其他线程,最终在某个线程中合并其他线程的结果

改进后:

public class CallableDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyThread myThread = new MyThread();

        FutureTask<Integer> futureTask = new FutureTask<>(myThread);

        Thread t1 = new Thread(futureTask,"t1");
        t1.start();
//        int result2 = futureTask.get();在此处会等待t1线程计算结束,将阻塞main线程
        System.out.println(Thread.currentThread().getName() + "*****");

        int result1 = 100;

        while (!futureTask.isDone()){

        }

        int result2 = futureTask.get();
        System.out.println("result:"+(result1+result2));

    }
}
class MyThread implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        System.out.println("**********call**********");
        // 模拟计算过程
        try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e){ e.printStackTrace(); }
        return 1024;
    }
}
  1. 能抛出异常
    多线程下,某个线程出错时可以通过抛出的异常更好的定位并发解决问题

本文地址:https://blog.csdn.net/weixin_44371151/article/details/107123794