【Java并发编程】Java多线程(三):创建任务 --Runnable、Callable

1.创建线程任务方式一:Runnable

Runnable#run() 实现线程逻辑, 无返回值

public interface Runnable {
    public abstract void run();
}

2.创建线程任务方式一:Callable

2.1 Callable

Callable#call() 实现线程逻辑,有返回值(V)

public interface Callable<V> {
    V call() throws Exception;
}

2.2 Future

Callabe 不能单独使用,需要 Future 用来控制 Callable 执行,获取 Callable 执行结果

public interface Future<V> {

	// 等待结果返回
    // 如果任务被取消了,抛 CancellationException 异常
    // 如果等待过程中被打断了,抛 InterruptedException 异常
    V get() throws InterruptedException, ExecutionException;

    // 等待,但是带有超时时间的,如果超时时间外仍然没有响应,抛 TimeoutException 异常
    V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;

    // 如果任务已经成功了,或已经取消了,是无法再取消的,会直接返回取消成功(true)
    // 如果任务还没有开始进行时,发起取消,是可以取消成功的。
    // 如果取消时,任务已经在运行了,mayInterruptIfRunning 为 true 的话,就可以打断运行中的线程
    // mayInterruptIfRunning 为 false,表示不能打断直接返回
    boolean cancel(boolean mayInterruptIfRunning);
	
    // 返回线程是否已经被取消了,true 表示已经被取消了
    // 如果线程已经运行结束了,isCancelled 和 isDone 返回的都是 true
    boolean isCancelled();

    // 线程是否已经运行结束了
    boolean isDone();
}

1)get 方法主要作用是得到 Callable 异步任务执行的结果,无参 get 会一直等待任务执行完成之后才返回,有参 get 方法可以设定固定的时间,在设定的时间内,如果任务还没有执行成功,直接返回异常,在实际工作中,建议多多使用 get 有参方法,少用 get 无参方法,防止任务执行过慢时,多数线程都在等待,造成线程耗尽的问题。

2)cancel 方法主要用来取消任务,如果任务还没有执行,是可以取消的,如果任务已经在执行过程中了,你可以选择不取消,或者直接打断执行中的任务

那么问题来了…

=> 两个问题

问题一:Callable 与 Future都是接口,怎么实现通过 Future 控制 Callable 呢?

答:可以创建一个中间类实现 Future接口,然后将 Callable 实例组合进来,最后通过 Future 接口中的方法实现控制。

问题二:另外,这里还要考虑一个问题,Runnable 和 Callable 都可以表示线程要执行的任务,那么这两个接口如何在不改变原有关系的基础上互相转化?

答:首先,Runnable 与 Callable 肯定不能通过 extends 实现,因为直接继承就是 is-a 的关系,而这俩显然不是。那么还有一个办法,引入一个中间类 F(满足以下两个条件)

  • F extends Runnable:继承 Runnable
  • F { primary Callable c }:组合 Callable

=> 最终,结合上面的所有分析,我们得到了 FutureTask 的结构:实现 Future 接口 & 实现Runnable接口 & 组合Callable

FutureTask 到底是怎么样的,请看下一篇文章 FutureTask 源码分析

  •  

猜你喜欢

转载自blog.csdn.net/qq_33762302/article/details/114342479
今日推荐