线程 sleep 取消_JAVA并发编程:线程并发工具类Callable、Future 和FutureTask的使用

4511aeca72f0fd0ed6552345f92a7796.gif

1、基本介绍

  Runnable 是一个接口,在它里面只声明了一个 run()方法,由于 run()方法返回值为 void 类型,所以在执行完任务之后无法返回任何结果。
  Callable 位于 java.util.concurrent 包下,它也是一个接口,在它里面也只声明 了一个方法,只不过这个方法叫做 call(),这是一个泛型接口,call()函数返回的类型就是传递进来的 V 类型。
  Future 就是对于具体的 Runnable 或者 Callable 任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过 get 方法获取执行结果,该方法会阻塞直到任务返回结果。在Future类中一共有5个方法,如下图所示。baa02270bb2e48c232856e3e4ba49ac3.png

  • cancel(boolean mayInterruptIfRunning) 方法:取消任务,如果任务已经完成、已经被取消或由于某些其他原因而无法取消,则此尝试将失败。如果成功,并且在调用{@code cancel}时此任务尚未开始,则该任务永远不会运行。如果任务已经开始,则{@code mayInterruptIfRunning}参数确定是否应中断执行该任务的线程以尝试停止该任务。

  • get() 方法:获取返回结果

  • get(long timeout, TimeUnit unit) 方法:获取结果时设置等待时长

  • isCancelled() 方法:如果此任务在正常完成之前被取消,则返回{@code true}。

  • isDone() 方法:如果此任务完成,则返回{@code true}。

  由于Future 只是一个接口,无法直接用来创建对象使用,因此就有了下面的FutureTask。FutureTask 类实现了RunnableFuture 接口,RunnableFuture 继承了Runnable接口和Future 接口,而FutureTask 实现了RunnableFuture 接口。所以它既可以作为Runnable被线程执行,又可以作为Future 得到Callable 的返回值。FutureTask,可取消的异步计算。此类提供{@link Future}的基本实现,其中包含启动和取消计算,查询以查看计算是否完成以及检索计算结果的方法。只有在计算完成后才能检索结果;如果计算尚未完成,则{@code get}方法将阻塞。一旦计算完成,就不能重新开始或取消计算(除非使用{@link #runAndReset}调用计算)。UML类图如下所示,可清晰看到几个类的关系。c35af3629a242553bb56b44146e2497a.png
  因此我们通过一个线程运行Callable,但是Thread 不支持构造方法中传递Callable的实例,所以我们需要通过FutureTask 把一个Callable 包装成Runnable,然后再通过这个FutureTask 拿到Callable 运行后的返回值。要new 一个FutureTask的实例,有两种方法,如下图所示。4a199bf820b3c04531dc011cf0fb0eb8.png

2、代码示例

  • 类说明:Future的基本使用

package cn.lspj.ch2.future;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
* 类说明:Future的使用
*/
public class UseFuture {

/**
* 实现Callable接口,允许有返回值
*/
private static class UseCallable implements Callable<Integer> {

@Override
public Integer call() throws Exception {
System.out.println("Callable 子线程开始计算。。。。。。");
int num = 0;
for(int i=0;i<5000;i++){
num += i;
}
System.out.println("Callable 线程计算结果为 num =" + num);
return num;
}
}

public static void main(String[] args) throws ExecutionException, InterruptedException {

UseCallable useCallable = new UseCallable();
// 包装
FutureTask futureTask = new FutureTask(useCallable);
new Thread(futureTask).start();
System.out.println("获取子线程Callable计算返回结果:" + futureTask.get());
}

}

执行结果如下:9fbb10a66cc4325ea9182cfb3b6bf5b6.png

  • 类说明:Future的使用,演示在计算过程中中断任务

package cn.lspj.ch2.future;

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
* 类说明:Future的使用,演示在计算过程中中断任务
*/
public class UseFuture {

/**
* 实现Callable接口,允许有返回值
*/
private static class UseCallable implements Callable<Integer> {

@Override
public Integer call() throws Exception {
System.out.println("Callable 子线程开始计算。。。。。。");
int num = 0;
for(int i=0;i<5000;i++){
if(Thread.currentThread().isInterrupted()){
System.out.println("Callable 子线程计算任务被中断了。。。。。。。。。。");
return null;
}
Thread.sleep(1);
num += i;
System.out.println("num=" + num);
}
System.out.println("Callable 线程计算结果为 num =" + num);
return num;
}
}

public static void main(String[] args) throws ExecutionException, InterruptedException {

UseCallable useCallable = new UseCallable();
// 包装
FutureTask futureTask = new FutureTask(useCallable);
new Thread(futureTask).start();
Thread.sleep(35);
Random r = new Random(10);
if(r.nextInt() > 5){
System.out.println("获取子线程Callable计算返回结果:" + futureTask.get());
} else {
System.out.println("cancle..............");
futureTask.cancel(true);
}
}

}

执行结果如下:55d91890d9fe66e0d2c21c3382755bc7.png
  从执行结果来看,在任务执行计算的过程中调用task的cancel(boolean mayInterruptIfRunning)方法中断任务是可以达到中断任务的目的,但是需要在执行计算的业务逻辑中使用Thread.currentThread().isInterrupted()判断任务是否中断,否则计算任务是不会主动中断的。


更多精彩内容请关注“菜鸟技术栈”微信公众号

0b1fbe2a68a8a64cd398c4e68e321306.png

CSDN:

https://blog.csdn.net/lspj201007186/article/details/106247283

往期内容:

JAVA并发编程:线程并发工具类CountDownLatch与CyclicBarrier的作用、应用场景和实战

JAVA并发编程:线程并发工具类Fork-Join原理分析及实战

算法:JAVA实现归并排序

算法:插入排序

并发编程:线程中Join方法的使用示例分析

并发编程:线程基础、JAVA新启线程的方式

详解Java 8 中使用Stream将List转为Map

MYSQL之limit基本用法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值