线程执行者(九)执行者取消一个任务

执行者取消一个任务

当你使用执行者工作时,你不得不管理线程。你只实现Runnable或 Callable任务和把它们提交给执行者。执行者负责创建线程,在线程池中管理它们,当它们不需要时,结束它们。有时候,你想要取消已经提交给执行者 的任务。在这种情况下,你可以使用Future的cancel()方法,它允许你做取消操作。在这个指南中,你将学习如何使用这个方法来取消已经提交给执行者的任务。

准备工作…

这个指南的例子使用Eclipse IDE实现。如果你使用Eclipse或其他IDE,如NetBeans,打开它并创建一个新的Java项目。

如何做…

按以下步骤来实现的这个例子:

1.创建Task类,指定实现Callable接口,并参数化为String类型。实现call()方法,写入一条信息到控制台,并使这个线程在循环中睡眠100毫秒。

1 public class Task implements Callable<String> {
2 @Override
3 public String call() throws Exception {
4 while (true){
5 System.out.printf("Task: Test\n");
6 Thread.sleep(100);
7 }
8 }

2.实现示例的主类,创建Main类,实现main()方法。

1 public class Main {
2 public static void main(String[] args) {

3. 使用Executors类的newCachedThreadPool()方法创建ThreadPoolExecutor对象。

1 ThreadPoolExecutor executor=(ThreadPoolExecutor)Executors.newCachedThreadPool();

4.创建Task对象。

1 Task task=new Task();

5.使用submit()方法提交任务给执行者。

1 System.out.printf("Main: Executing the Task\n");
2 Future<String> result=executor.submit(task);

6.使主任务睡眠2秒。

1 try {
2 TimeUnit.SECONDS.sleep(2);
3 } catch (InterruptedException e) {
4 e.printStackTrace();
5 }

7.使用通过submit()方法返回的Future对象result的cancel()方法,取消任务的执行。传入true值作为cancel()方法的参数。

1 System.out.printf("Main: Canceling the Task\n");
2 result.cancel(true);

8.将isCancelled()方法和isDone()的调用结果写入控制台,验证任务已取消,因此,已完成。

1 System.out.printf("Main: Canceled: %s\n",result.isCanceled());
2 System.out.printf("Main: Done: %s\n",result.isDone());

9.使用shutdown()方法结束执行者,写入信息(到控制台)表明程序结束。

1 executor.shutdown();
2 System.out.printf("Main: The executor has finished\n");

它是如何工作的…

当你想要取消你已提交给执行者的任务,使用Future接口的cancel()方法。根据cancel()方法参数和任务的状态不同,这个方法的行为将不同:

  • 如果这个任务已经完成或之前的已被取消或由于其他原因不能被取消,那么这个方法将会返回false并且这个任务不会被取消。
  • 如果这个任务正在等待执行者获取执行它的线程,那么这个任务将被取消而且不会开始它的执行。如果这个任务已经正在运行,则视方法的参数情况而定。 cancel()方法接收一个Boolean值参数。如果参数为true并且任务正在运行,那么这个任务将被取消。如果参数为false并且任务正在运行,那么这个任务将不会被取消。

以下截图显示该示例的执行输出:

不止这些…

如果你使用Future对象的get()方法来控制一个已被取消的任务,这个get()方法将抛出CancellationException异常。

参见

  • 在第4章,线程执行者中的执行者执行返回结果的任务指南
时间: 2025-01-30 03:53:19

线程执行者(九)执行者取消一个任务的相关文章

线程执行者(八)执行者周期性地运行一个任务

执行者周期性地运行一个任务 执行者框架提供ThreadPoolExecutor类,使用池中的线程执行并发任务,从而避免所有线程的创建操作.当你提交任务给执行者,根据它的配置,它尽快地执行任务.当它结束,任务将被执行者删除,如果你想再次运行任务,你必须再次提交任务给执行者. 但是执行者框架通过ScheduledThreadPoolExecutor类可以执行周期性任务.在这个指南中,你将学习如何通过使用这个类的功能来安排一个周期性任务. 准备工作- 这个指南的例子使用Eclipse IDE实现.如果

android-用户按下返回键取消一个警告对话框的触发事件

问题描述 用户按下返回键取消一个警告对话框的触发事件 当用户按下返回键并且想要取消对话框时,我需要捕捉一个事件. 代码是这样的: AlertDialog alertDialog = new AlertDialog.Builder(AppNotification.this).create(); alertDialog.setTitle("Caution"); alertDialog.setMessage("Alert"); alertDialog.setButton(

多线程-JAVA中如何在一个线程里面停掉另一个线程

问题描述 JAVA中如何在一个线程里面停掉另一个线程 JAVA中如何在一个线程里面停掉另一个线程,是在一个线程里面哦 PS:新人第一次问问题,希望大神求教 解决方案 定义一个共享变量在run方法里面 while(start){ } 解决方案二: 所以说,这个问题的答案是:不可以! 虽然的确有那么个方法可以摧毁别人的线程,但很早很早就已经过期了,如果没记错的话我之前也这么玩,而结果是这个过期的方法根本没有作用-- 虽然说办法不是没有,那就是通过改变变量值,它知道自己该死了,就退出循环,走向结束.

定制并发类(九)实现一个自定义的Lock类

声明:本文是< Java 7 Concurrency Cookbook >的第七章,作者: Javier Fernández González     译者:许巧辉 实现一个自定义的Lock类 锁是Java并发API提供的基本同步机制之一.它允许程序员保护代码的临界区,所以,在某个时刻只有一个线程能执行这个代码块.它提供以下两种操作: lock():当你想要访问一个临界区时,调用这个方法.如果有其他线程正在运行这个临界区,其他线程将阻塞,直到它们被这个锁唤醒,从而获取这个临界区的访问. unl

跨线程 调试-c# 多线程的一个问题请各位多多指点

问题描述 c# 多线程的一个问题请各位多多指点 小弟刚刚学习c#多线程的知识,今天测试一个简单的windows窗口程序,程序主要内容为: private void add_item() { for (int i = 0; i < 100000; i++) { this.listBox1.Items.Add(i.ToString() + " aa "); } } private void button1_Click(object sender, EventArgs e) { Thr

线程-sql 找错,一个很奇怪的错误

问题描述 sql 找错,一个很奇怪的错误 sql = "UPDATE bs2_dl_road_min SET count=count+{0} WHERE time='{1}' " "AND host_ip='{2}' AND module='{3}' AND method='{4}' AND status='{5}' " "AND size_level='{6}' AND level='{7}' AND submodule_road='{8}'"

c#中子线程控制进度条的一个简单例子

这个问题来自社区提问,代码保留一份用来以后回答 using System; using System.ComponentModel; using System.Windows.Forms; namespace WindowsApplication4 ...{ /**//// <summary> /// gui 类 /// </summary> public partial class Form1 : Form ...{ public Form1() ...{ InitializeC

java 线程 sql qualz-如何写一个定时任务要每月的1号01:00执行这个sql

问题描述 如何写一个定时任务要每月的1号01:00执行这个sql 1C insert into test_dept_monthhours(yearmonthbranchsubtotal) select yearmonthbranchsum(dm)+sum(sm)+sum(smt)+sum(sup)+sum(ltnc) from ehruser.HO_DEPT_MONTHHOURS@traininglink where rownum<5 group by branchyearmonth 解决方案

线程执行者(三)创建一个大小固定的线程执行者

创建一个大小固定的线程执行者 当你使用由Executors类的 newCachedThreadPool()方法创建的基本ThreadPoolExecutor,你会有执行者运行在某一时刻的线程数的问题.这个执行者为每个接收到的任务创建一个线程(如果池中没有空闲的线程),所以,如果你提交大量的任务,并且它们有很长的(执行)时间,你会使系统过载和引发应用程序性能不佳的问题. 如果你想要避免这个问题,Executors类提供一个方法来创建大小固定的线程执行者.这个执行者有最大线程数. 如果你提交超过这个