并发编程实战 - [任务执行、取消与关闭]

1、任务执行

1.1、Executor

1.1.1、线程池与Executor生命周期

Executor基于生产者-消费者模式,我们可以通过Executors的四个静态工厂方法创建线程池:newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor、newScheduledThreadPool。这四个工厂方法其实都是通过ThreadPoolExecutor来创建的,只是传递的参数不同[主要是工作队列的不同]罢了。
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
其中,workQueue是工作队列,工作队列中保存了所有等待执行的任务,工作线程的任务很简单:从工作队列中获取一个任务,执行任务,然后返回线程池并等待下一个任务。
ThreadFactory用于创建新的线程。
Executor的实现通常是创建线程来执行任务,但JVM只有在所有的(非守护)线程全部终止后才会退出。因此,如果无法正确地关闭Executor,那么JVM将无法结束。
为了解决执行服务的生命周期问题,Executor扩展了ExecutorService接口,添加了一些用于生命周期管理的方法(同时还有一些用于任务提交的便利方法)。

ExecutorService的生命周期有三种状态:运行、关闭和已终止。ExecutorService在初始创建的时候,处于运行状态。shutDown方法将执行平缓的关闭过程:不再接收新的任务,同时等待已经提交的任务执行完成 - 包括那些还未开始执行的任务。shutDownNow方法将执行粗暴的关闭过程:它将尝试取消所有运行中的任务,并且不再启动队列中尚未开始执行的任务。
在ExecutorService关闭后提交的任务将由“拒绝执行处理器”来处理,它会抛弃任务,或者使得execute方法抛出一个未检查RejectedException异常。等待所有的任务执行完成,ExecutorService将转入终止状态。可以调用awaitTermination来等待ExecutorService到达终止状态,或者通过调用isTerminated来轮询ExecutorService是否已经终止。

1.1.2、延迟任务与周期任务

Timer在执行所有定时任务时只会创建一个线程,如果某个任务的执行时间过长,那么将破坏其他TimerTask的定时准确性。【Timer支持基于绝对时间而不是相对时间的调度机制,而ScheduledThreadPoolExecutor只支持基于相对时间的调度】。
Timer的另一个问题,如果TimerTask抛出了一个未检查异常,那么Timer将表现糟糕的行为。Timer线程并不捕获异常,因此当TimerTask抛出未检查异常时将终止定时线程。这种情况下,Timer也不会恢复线程的执行,而是会错误的认为整个Timer都被取消了。因此,已经被调度但尚未执行的TimerTask将不会再执行,新的任务也不能被调度。(这个问题被称为“线程泄露”)。
Timer存在一些缺陷,因此应该考虑使用ScheduledThreadPoolExecutor来代替它。在JDK5.0 或者更高的JDK中,将很少使用Timer。

1.1.3、Callable与Future

Executor框架使用Runnable作为其基本的任务表示形式。Runnable是一种有很大局限的抽象,虽然run能写入日志文件或者将结果放入某个共享的数据结构,但它不能返回一个值或抛出一个受检查异常。
许多任务实际上都是存在延迟的计算 - 执行数据库查询,从网络获取一个资源等,对于这些任务,Callable是一种更好的抽象:它认为主入口点(Call)将返回一个值,并可能抛出一个异常。在Executor中包含了一些辅助方法能将其他类型的任务封装成一个Callable,例如Runnable和java.security.PrivilegedAction。
Executor执行的任务有四个生命周期:创建、提交、开始和完成。在Executor框架中,已经提交但尚未开始的任务可以取消,但对于那些已经开始执行的任务,只有当它们中断时,才能取消。取消一个已经完成的任务不会有任何影响。
Future表示一个任务的生命周期,并提供了相应的方法来判断是否已经完成或取消,以及获取任务的结果和取消任务等。在Future规范中包含的隐含意义是,任务的生命周期只能前进,不能后退,就像ExecutorService的生命周期一样。当某个任务执行完成后,它就永远停留在“完成”状态。
get方法的行为取决于任务的状态(尚未开始、正在执行、已完成)。如果任务已经完成,get将立即返回或者抛出一个Exception。如果任务没有完成,那么get将阻塞直到任务完成。
ExecutorService中的所有submit方法都将返回一个Future,从而将一个Runnable或Callable提交给Executor。并得到一个Future用来获得任务的执行结果或取消任务。还可以显式地为某个指定的Runnable或Callable实例化一个FutureTask(由于FutureTask实现了Runnable,因此可以将它提交给Executor来执行,或者直接调用它的run方法)。
在将Runnable或Callable提交到Executor的过程中,包含了一个安全发布过程,即将Runnable或Callable从提交线程发布到最终执行任务的线程。类似的,在设置Future结果的过程中也包含了一个安全发布,即将这个结果从计算它的线程发布任何通过通过get获取它的线程。
public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}
注意:只有当大量相互独立且同构的任务可以并发进行处理时,才能体现出将程序的工作负载分配到多个任务中带来的真正性能提升。

1.2、CompletionService

需求场景:向Executor提交一组计算任务,并且希望在计算完成之后获得结果。
解决方式:保留与每个任务关联的Future,然后反复使用get方法,同时将参数timeout指定为0,从而通过轮询来判断任务是否完成。
缺点:可行,但是繁琐。
优雅的解决方式:CompletionService。
CompletionService将Executor和BlockingQueue的功能融合在一起。你可以将Callable任务提交给给它执行,然后使用类似队列操作的take和poll等方法来获得已完成的结果,而这些结果在完成时将被封装成Future。ExecutorCompletionService实现了CompletionService并将计算部分委托给一个Executor。
public ExecutorCompletionService(Executor executor)
public ExecutorCompletionService(Executor executor,
                                     BlockingQueue<Future<V>> completionQueue) 
 public Future<V> submit(Callable<V> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<V> f = newTaskFor(task);
        executor.execute(new QueueingFuture(f));
        return f;
    }

    public Future<V> submit(Runnable task, V result) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<V> f = newTaskFor(task, result);
        executor.execute(new QueueingFuture(f));
        return f;
    }
ExecutorCompletionService的实现很简。在构造函数中创建一个BlockingQueue来保存计算完成的结果。当计算完成时,调用FutureTask中的done方法。当提交某个任务时,该任务将首先包装成一个QueueingFuture,这是一个FutureTask的一个子类。
private class QueueingFuture extends FutureTask<Void> {
        QueueingFuture(RunnableFuture<V> task) {
            super(task, null);
            this.task = task;
        }
        protected void done() { completionQueue.add(task); }
        private final Future<V> task;
    }
可以看到,task在被包装时,同时被放到了BlockingQueue中。前面说了,这个done方法会在计算完成时,放到BlockingQueue中。
public Future<V> take() throws InterruptedException {
        return completionQueue.take();
    }

    public Future<V> poll() {
        return completionQueue.poll();
    }
take和poll方法在得到结果之前阻塞。多个ExecutorCompletionService可以共享一个Executor,因此可以创建一个对于特定计算私有,又能共享一个公共Executor的ExecutorCompletionService。

1.3、为任务设定时限

在支持时间限制的Future.get中支持这种需求:当结果可用时,它将立即返回。如果在指定的时间内没有计算结果,那么将抛出TimeOutException异常,可以在抛出异常时,取消任务。
V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
支持限时的invokeAll,将多个任务提交到一个ExecutorService并获得结果。InvokeAll方法的参数为一组任务,并返回一组Future。invokeAll按照任务集合中迭代器的顺序将所有的Future添加到返回的集合中,从而使调用者能将各个Future与其表示的Callable关联起来。当所有任务都执行完毕时,或者调用线程被中断时,又或者超时指定时限时,invokeAll将返回。当invokeAll返回后,每个任务要么正常的完成。要么被取消,而客户端代码可以调用get或isCancelled来判断究竟是何种情况。
----------------------------------------------------

2、取消与关闭

要使任务和线程能安全、快速、可靠地停止下来,并不是一件容易的事情。Java没有提供任何机制来安全地终止线程【虽然Thread.stop和Thread.suspend等方法提供了这样的机制,但由于存在着严重的缺陷,因此应该避免使用】。但它提供了中断,这是一种协作机制,能够使一个线程终止另一个线程的当前工作。这种协作的方式是有必要的,我们很少希望某个任务、线程或服务立即停止,因为这种立即停止会使共享的数据结构处于不一致的状态。相反,在编写任务和服务时可以使用一种协作的方式:当需要停止时,它们首先会清除当前正在执行的工作,然后再结束。这提供了更好的灵活性。因为任务本身的代码比发出取消请求的代码更清除如何执行清除工作。
在Java的Api或语言规范中,并没有将中断与任何取消语义关联起来,但实际上,如果在取消之外的其他操作中使用中断,那么都是不合适的,并且很难支撑起来很大的应用。
每个线程都有一个boolean类型的中断状态。当中断线程时,这个线程的中断状态将设置为true。
interrupt()方法能中断目标线程。【注意:调用该方法并不意味着立即停止目标线程正在进行的工作,而只是传递了请求中断的消息】
isInterrupt()方法能返回目标线程的中断状态;
interrupted()将清除当前线程的中断状态,并返回它之前的值,这也是清除中断状态的唯一方法。
阻塞库方法,例如Thread.sleep和Object.wait等,都会检查线程何时中断,并且在发生中断时提前返回。它们在响应中断时执行的操作包括:清除中断状态,抛出InterruptionException,表示阻塞操作由于中断而提前结束。JVM并不能保证阻塞方法检测到中断的速度,但在实际情况中响应速度还是非常快的。
当线程在非阻塞状态下中断时,中断状态将被设置,然后根据将被取消的操作来检查中断状态以判断发生了状态。
对中断的正确理解:它并不会真正地中断一个正在运行的线程,而只是发出中断请求,然后由线程在下一个合适的时刻中断自己。有些方法。例如sleep、wait、join等,将严格的处理这种请求,当它们收到中断请求或者在开始执行时发现某个已被设置好的中断状态时,将抛出一个异常。
在使用静态的interrupted时应该小心,因为它会清除当前现成的中断状态。如果在调用interrupted时返回true,那么除非你想屏蔽这个中断,否则必须对它进行处理-可以抛出interruptionException,或者通过再次调用interrupt来恢复中断状态。
注意:通常,中断时实现取消的最合理方式。
public   class BrokenPrimerProduce extends Thread{
        
        private final BlockingDeque<BigInteger> queue;
        private volatile boolean canceled = false;
        
        public BrokenPrimerProduce(BlockingDeque<BigInteger> queue){
            this,queue = queue;
        }
        
        public void run(){
            try{
                BigInteger p = BigInteger.ONE;
                while (!canceled){
                    queue.put(p = p.nextProbablePrime());
                }
            }catch (InterruptedException e){
            }
        }
        public void cancel(){
            canceled = true;
        }
    }
上述这段代码有什么问题呢?如果队列已满,则put会阻塞,而此时如果消费者线程取消了任务,调用了cancel方法,那么此时生产者将用于无法检测到cancel标志,因为它无法从被阻塞的put方法中恢复过来。
解决方式:
public   class BrokenPrimerProduce extends Thread{

        private final BlockingDeque<BigInteger> queue;

        public BrokenPrimerProduce(BlockingDeque<BigInteger> queue){
            this,queue = queue;
        }

        public void run(){
            try{
                BigInteger p = BigInteger.ONE;
                while (!Thread.currentThread().isInterrupted()){
                    queue.put(p = p.nextProbablePrime());
                }
            }catch (InterruptedException e){//在catch里面,允许线程退出
            }
        }
        public void cancel(){
        interrupt();//导致阻塞put抛出interruptionException异常
        }
    }

2.1、响应中断

在调用可中断的阻塞函数时,例如Thread.sleep或BlockingQueue.put等,有两种实用策略可用于处理InterruptException:
a)传递异常(可能在执行某个特定的清除操作之后),从而使你的方法也成为可中断的阻塞方法;
b)恢复中断状态,从而使得调用栈的上层代码能够对其进行处理,一种标准的方法就是通过再次调用interrupt方法来恢复中断状态;
你不能屏蔽InterruptedException,例如在catch块中捕获到异常却不做任何处理,除非在你的代码中实现了线程的中断策略。由于大多数代码并不知道它们将在哪个线程中运行,因此应该保存中断状态。
注意:只有实现了线程中断策略的代码才可以屏蔽中断请求。在常规的任务和库代码中都不应该屏蔽中断请求。

2.2、通过Future来实现取消

通常,使用现有库中的类比自行编写更好。ExecutorService.submit将返回一个Future来描述任务。Future拥有一个cancel方法,该方法带有一个boolean类型的参数mayInterruptIfRunning,表示取消操作是否成功。(这只是表示任务是否能够接收中断,而不是表示任务是否能检测并处理中断)。如果mayInterruptIfRunning为true并且任务当前正在某个线程中运行,那么这个线程能被中断。这个参数为false,那么意味着“若任务还没有启动,就不要运行它”,这种方式应该用于那些不处理中断的任务中。
除非你清楚线程的中断策略,否则不要中断线程,那么在什么情况下调用cancel方法可以指定参数为true呢?
执行任务的线程是由标准的Executor创建的,它实现了一种中断策略使得任务可以通过中断被取消,所以如果任务在标准Executor中运行,并通过它们的Future来取消任务,那么可以设置mayInterruptIfRunning。当尝试取消某个任务时,不宜直接中断线程池,因为你并不知道当中断请求到达时正在运行什么任务 - 只能通过任务的Future来实现取消。
【当Future.get抛出InterruptException或者TimeoutException时,如果你知道不再需要结果,那么就可以调用Future.cancel来取消任务】

2.3、处理不可中断的阻塞

在Java库中,许多可阻塞的方法都是通过提前返回或者抛出InterruptException来响应中断请求的,从而使得开发人员更容易构建出能响应取消请求的任务。然而,并非所有的可阻塞方法或者阻塞机制都能响应中断:如果一个线程由于执行同步Socket I/O或者等待获得内置锁而阻塞,那么中断请求只能设置线程的中断状态,除此之外,没有其他任何作用。对于那些由于执行不可中断操作而被阻塞的线程,可以使用类似中断的手段来停止这些线程。比如改写interrupt方法等。
硬全桥副边钳位管Vds电压凸台揭秘——寄生参数引发的导通异常 本文深入分析了硬全桥副边钳位管Vds电压凸台现象,揭示了寄生参数如何引发导通异常。通过波形分析和工程实践,详细解析了走线电感的蓄能效应和体二极管的接力作用,并提供了PCB布局优化、元件选型和驱动电路调整等解决方案,帮助工程师有效应对这一常见问题。 阅读详情

相关推荐

Modelica建模,Modelica语言的学习,技术调研工作

Modelica是由Modelica协会维护、免费开放的物理系统面向对象的统一建模语言规范,为机、电、液、控等多领域复杂工程系统提供了统一的物理建模语言规范。 Modelica作为多学科统一建模仿真的国际标准,被仿真界广泛采用,系统多领域统一建模仿真,已成为世界公认的MBSE和CPS的核心关键支持技术。 Modelica 语法、函数、包、连接器、组件、子系统

xzb5566的专栏 4636

JAVA并发编程(四)任务的取消与关闭

使用简单标志位保存取消状态 为了保证标志位可靠,标志必须为volatile类型。 使用标志位来取消任务是不及时的,如果中间调用了阻塞方法,有可能永远都无法结束。 每个线程都有一个boolean类型的中断状态,interrupt方法能中断目标线程,而isInterrupted方法能返回目标线程的中断状态,静态的interrupted方法将清除当前线程的中断状态,也是清除中断状态的唯一一个方法。 在线上Java程序中经常遇到进程程挂掉,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的

robert的专栏 7343

CV领域交叉注意力机制:QKV在图像特征增强中的核心作用解析

本文深入解析了CV领域中交叉注意力机制的核心组件QKV在图像特征增强中的关键作用。通过通俗类比和实战案例,阐述了Q(查询)、K(键)、V(值)如何协同实现动态权重分配,从而在目标检测、图像分割与生成等任务中显著提升模型性能与语义对齐能力。

weixin_29194817的博客 434

js处理并发请求

1,Promise并行执行异步任务。 试想一个页面聊天系统,我们需要从两个不同的URL分别获得用户的个人信息和好友列表,这两个任务是可以并行执行的,用Promise.all()实现如下: var p1 = new Promise(function (resolve, reject) { setTimeout(resolve, 500, 'P1'); }); var p2 = new ...

qq_31965515的博客 7059

手把手教你:基于STM32H7自制飞控,如何从零开始移植PX4固件(附避坑指南)

本文详细介绍了如何基于STM32H7自制飞控板并移植PX4固件的完整流程,包括硬件设计、开发环境搭建、关键配置文件移植、驱动开发与适配等关键步骤。特别针对PX4-AutoPilot的移植过程提供了实用技巧和避坑指南,帮助开发者高效完成飞控系统开发。

weixin_30271335的博客 143

向量数据库安全实战:从Embedding反推到检索越权的全链路防护

随着RAG应用在企业中的普及,向量数据库已成为知识库系统的核心组件。但许多团队对向量数据的安全认知仍停留在传统数据库的账号密码、网络隔离和磁盘加密上。事实上,向量化并非加密,而是一种有损压缩的语义映射,向量本身可以被反推模型还原出原文关键信息,形成高保真的语义泄露通道。同时,相似度检索的模糊匹配特性打破了传统行列权限模型,使得越权检索和成员推断攻击成为新的安全威胁。理解这些原理,有助于企业在数据采集、向量化、索引构建、检索查询等环节构建分层防护体系,包括脱敏、扰动、过滤下推、网关控制等手段。本文从基础概念出

weixin_29323551的博客 259

ThreadPoolTaskScheduler 调度了延迟任务成功,在延迟时间内怎么取消呢?

ThreadPoolTaskScheduler配置线程池 import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; @Configuration public class TaskSche.

print的博客 1万+

ABAP CURR Data Type 深度解析与实战案例

CURR 数据类型是 SAP ABAP 中为处理货币金额而设计的一种特殊数据类型。CURR 数据类型能够自动根据关联的货币代码字段(例如 WAERS)确定小数位数,从而保证金额数据的精度与正确性。CURR 类型通常在 SAP 数据字典中使用,常见于各类业务数据表中,如会计凭证、销售订单等场景中,用于存储货币金额。CURR 数据类型底层实现上类似于 DEC 数据类型,但其特别之处在于与货币代码字段的绑定,这使得金额的格式化和显示可以自动匹配相应的货币规则。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 876

线程池-停止任务与取消任务

它本身并不是用来关闭线程池的,而是主要用来判断线程池状态的当前线程会尝试等待一段指定的时间,如果在等待时间内,线程池已关闭并且内部的任务都执行完毕了,也就是说线程池真正“终结”了,那么方法就返回 true,否则超时返回 fasle在执行 shutdownNow 方法之后,首先会给所有线程池中的线程发送 interrupt 中断信号,尝试中断这些任务的执行,然后会将任务队列中正在等待的所有任务转移到一个 List 中并返回,我们可以根据返回的任务 List 来进行一些补救的操作,

存在,即合理 904

《MATLAB项目实战》,专栏目录和介绍

MATLAB 是一款强大且广泛应用的数值计算和数据可视化软件工具,它提供了一个高效、简洁的编程环境,使用户能够进行从简单的矩阵运算到复杂的多维数据分析的各种计算任务。无论是在人工智能、计算机视觉、图像处理还是其他领域,MATLAB 都能够提供精准、快速的解决方案,因此成为了全球科研人员、工程师以及数据分析师的得力工具。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 6473

ABAP 百科全书的阅读目录(2024版)

909 篇 ABAP 技术文章的目录

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 4244

java源码-ThreadPoolExecutor(2)

开篇  这篇文章的主要目标是为了讲解清楚ThreadPoolExecutor的提交任务的过程,非常推荐静下心来仔细阅读。java源码-ThreadPoolExecutor(1)java源码-ThreadPoolExecutor(2)java源码-ThreadPoolExecutor(3) ThreadPoo...

weixin_34324081的博客 192

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

《Java并发编程实战》 任务执行和取消关闭

http://blog.youkuaiyun.com/androiddevelop/article/details/27299357   Java没有提供任何机制来安全地(抢占式方法)终止线程,虽然Thread.stop和suspend等方法提供了这样的机制,但是由于存在着一些严重的缺陷,因此应该避免使用。但它提供了中断Interruption机制,这是一种协作机制,能够使一个线程终止另一个线程的当前工

清文的博客 2524

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

《Java并发编程实战》学习笔记 任务执行和取消关闭

查看豆瓣读书 第六章 任务执行 大多数并发应用程序是围绕执行任务进行管理的。设计任务时,要为任务设计一个清晰的任务边界,并配合一个明确的任务执行策略。任务最好是独立的,因为这会提高并发度。大多数服务器应用程序都选择了下面这个自然的任务边界:单个客户请求。 任务时逻辑上的工作单元,线程是使任务异步执行的机制。 应用程序内部的任务调度,存在多种可能的调度策略: 其中,最简单的策略是在

Happy_wu的专栏 533

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

《Java并发编程实战》第6、7章学习笔记

第五周学习心得 本周进行了《Java并发编程实战》第6、7章的学习,第6章主要通过围绕任务执行来设计应用程序,侧重于对Executor的使用。第7章主要讲了任务、线程和服务的取消与关闭操作带来的潜在问题以及如何避免这些问题。 任务执行——针对Executor的使用 在设计多线程应用程序时,需要明确任务的边界以及选择合理的任务执行策略,以便于更好的进行线程代码的独立编写。 大多数服务器应用程序都提供了一种自然的任务边界选择方式:以用户请求为任务边界。 无限制创建线程的不足: 线程生命周期的开销非常高

weixin_45207474的博客 189

【Java并发编程实战】

本篇是阅读《Java 并发编程实战》的零碎笔记,整体非常凌乱,并不适合阅读,仅做个人备忘。

猫吻鱼的博客 1474

读书笔记-《Java并发编程实战》

个人博客: https://zongwenlong.github.io/ 欢迎访问 ^_^  寒假在家认真阅读了《Java并发编程实战》(英文名:Java Concurrency in Practice) 一书,过程中碰到了许多问题和值得深究的内容。在实际编程实践的同时,随手将个人疑惑的知识点通过查询相关资料进行补充说明,整理到了GitHub上。笔记目录 Java Concurrent Tools

All is well ^_^ 329

《java并发编程实战》 第七章 任务、线程的取消与关闭

《java并发编程实战笔记》第七章 任务、线程的取消与关闭任务如何取消通过判断volatile类型的状态量----不一定可靠通过中断-----实现取消最合理方法 第七章 任务、线程的取消与关闭 要使任务和线程安全、快速、可靠的停止下来,并不是一件容易的事情。java没有提供任何机制来安全地终止线程,但提供了中断协作机制,中断能使一个线程终止另一个线程的当前工作。 任务如何取消 任务取消的原因有很多...

乌鸦大大 1180

java并发编程-取消与关闭

2、使用线程的interrupt()方法,会给当前线程的boolean类型的中断状态设置为true。任务本身仍只是一个 Callable,但通过 Executor.newTaskFor 钩子,把自定义的资源级取消逻辑注入到了 Future.cancel() 中,从而在不改变使用方式的前提下,增强了取消语义。线程的所有权是不可以传递的,应用程序可以拥有服务,服务可以拥有工作者线程,但是应用程序不能拥有工作者线程,因此应用程序不能直接停止工作者线程。这时任务是执行了,但是线程池没有记录,还是未执行完的状态。

weixin_52917644的博客 749

并发编程6:任务或线程的取消与关闭

Java 提供了中断 (Interruption)协作机制,通过该机制能够使一个线程终止另一个线程的当前工作。这种协作式的方法是必要的,我们很少希望某个任务、线程或服务立即停止,因为这种立即停止会使共享的数据结构处于不一致的状态。相反,在编写任务和服务时可以使用一种协作的方式:当需要停止时,它们首先会清除当前正在执行的工作,然后再结束。这提供了更好的灵活性,因为任务本身的代码比发出取消请求的代码更清楚如何执行清除工作。//中断操作应该由中断线程本身去决定何时中断。

swadian2008的博客 751

JAVA并发编程实战-取消和关闭

目录前言1 任务取消1.1 中断 前言 有时候我们希望任务或者线程自然结束前就停止它们,可能用户点击取消或者应用程序需要关闭。Java中提供了中断使一个线程可以要求另一个线程停止当前工作。 1 任务取消 可取消的活动:当外部代码能够在活动自然完成前,将其状态改为完成状态。 可能有多种原因导致活动关闭如: 用户请求的取消。用户点击取消按钮。 限时活动。设置超时器,如果超出停止活动。 应用程序事件,任务分解搜索,一个任务搜索到,停止其它任务。 错误。当多个任务保存页面,一个遇到磁盘满,其它取消。 关闭。当

qq_36566262的博客 1500

Java并发编程实战 第7章 取消与关闭

Java没有提供任何机制来安全地终止线程。但它提供了中断,这是一种协作机制,能够使一个线程终止另一个线程的当前工作。这种协作方法是必要的,我们很少希望某个任务、线程或服务立即停止,因为这种立即停止会使共享数据结构处于不一致的状态。在编写任务和服务时可以使用一种协作的方式:当需要停止时,它们首先会清楚当前旨在执行的工作,然后再结束。任务本身比发出取消请求的代码更清楚如何执行清除工作。行为良好的软件能很完善的处理失败、关闭和取消等过程。 7.1 任务取消 在Java中没有一种安全的抢占式方法来停止线程。只有一些

可可西里 295

任务执行与取消

任务执行 任务是一组逻辑业务单元,通常是一些抽象的且离散的工作单元,线程则是使任务异步执行的机制。 围绕“任务执行”来设计应用程序时,首先要做的就是找出清晰的任务边界。理想情况下任务之间应该是相互独立的,且不依赖于其他任务的状态、结果和边界效应。对于大多数服务器的应用程序而言,以独立的客户请求为边界。 有2中任务执行策略: 串行执行。所有任务都在一个线程中,顺序执行。串行的任务执行吞吐

老睿的专栏 1270

java并发编程(六)取消与关闭

接《java并发编程(五)任务执行》 前面几章我们一直是创建和开启线程,而有时候我们要结束任务或线程,这并不是很容易的,因为,java 并没有提供任何机制来安全终止线程(在未来的jdk版本中会不会加入呢?)它提供了中断。这是一种机制,能够在一个线程终止另一个线程的工作。 任务取消 一种协作方式是设置某个“已请求取消”标识,而任务将定时查看该标志。下面程序,将持续枚举素数,直到它将被取消。ca

p_max的专栏 658
上一篇: 并发编程实战 - 基础部分[对象的组合、基础构建模块]
下一篇: 架构思考之MVC、MVP、谷歌架构组件
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值