shutdownNow的局限性
shutdownNow是强行关闭ExecutorService的,它会尝试取消正在执行的任务,并返回所以已提交但尚未开始的任务,但是我们无法通过常规方法来找出哪些任务已经开始但尚未结束。这意味着我们无法在关闭过程中知道正在执行的任务的状态,除非任务本身会执行某种检查。为此,设计了一个TrackingExecutor类跟踪在关闭之后被取消的任务,getCancelledTasks返回被取消的任务清单。要使这项技术能发挥作用,任务在返回时必须维持线程的中断状态。具体代码如下:
public class TrackingExecutor extends AbstractExecutorService { private final ExecutorService exec = Executors.newCachedThreadPool(); private final Set<Runnable> tasksCancelledAtShutdown = Collections.synchronizedSet(new HashSet<Runnable>()); public List<Runnable> getCancelledTasks(){ if(!exec.isTerminated()){ throw new IllegalStateException("线程尚未中断"); } return new ArrayList<Runnable>(tasksCancelledAtShutdown); } @Override public void execute(final Runnable runnable) { exec.execute(new Runnable() { @Override public void run() { try{ runnable.run(); }finally{ if(isShutdown() && Thread.currentThread().isInterrupted()){ tasksCancelledAtShutdown.add(runnable); } } } }); } /*----------------------将ExecutroService的其他方法委托给exec---------------------------------*/ @Override public void shutdown() { // TODO Auto-generated method stub exec.shutdown(); } @Override public List<Runnable> shutdownNow() { // TODO Auto-generated method stub return exec.shutdownNow(); } @Override public boolean isShutdown() { // TODO Auto-generated method stub return exec.isShutdown(); } @Override public boolean isTerminated() { // TODO Auto-generated method stub return exec.isTerminated(); } @Override public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { // TODO Auto-generated method stub return exec.awaitTermination(timeout, unit); } }
使用TrackingExecutorService保存未完成的任务以备后续执行,代码如下:
public abstract class WebCrawler { private static final long TIMEOUT = 1; private static final TimeUnit UNIT = TimeUnit.MILLISECONDS; private volatile TrackingExecutor exec; @GuardedBy("this") private final Set<URL> urlsToCrawl = new HashSet<URL>(); public synchronized void start(){ exec = new TrackingExecutor(Executors.newCachedThreadPool()); for(URL url : urlsToCrawl){ submitCrawlTask(url); } urlsToCrawl.clear(); } public synchronized void stop() throws InterruptedException{ try{ saveUncrawled(exec.shutdownNow()); if(exec.awaitTermination(TIMEOUT, UNIT)){ saveUncrawled(exec.getCancelledTasks()); } }finally{ exec = null; } } private void saveUncrawled(List<Runnable> uncrawled){ for(Runnable task : uncrawled){ urlsToCrawl.add(((CrawlTask) task).getPage()); } } private void submitCrawlTask(URL url) { exec.execute(new CrawlTask(url)); } protected abstract List<URL> processPage(URL url); private class CrawlTask implements Runnable{ private final URL url = null; public CrawlTask(URL url2) { } public void run(){ for(URL link : processPage(url)){ if(Thread.currentThread().isInterrupted()){ return; } submitCrawlTask(link); } } public URL getPage(){return url;} } }
其中在 TrackingExecutor中存在一个不可避免的竞态条件,从而产生“误报”问题:一些被认为已取消的任务实际上已经执行完成。这个问题的原因在于,任务执行最后一条指令以及线程池将任务记录为“结束”的两个时刻之间,线程池可能被关闭。如果任务是幂等的(Idempotent,即将任务执行两次与执行一次会得到相同的结果),那么这不会存在问题,在网页爬虫程序中就是这种情况。否则,在应用程序中必须考虑这种风险,并对“误报”问题做好准备。
相关推荐
Java作为一种广泛使用的编程语言,具有跨平台的特性,使得它在并行计算领域也占据了一席之地。下面将详细介绍Java并行计算的相关知识点。 1. **Java多线程基础**:Java并行计算的核心在于多线程技术。Java提供了...
### 基于Web的Java并行计算 #### 摘要 本文深入探讨了如何运用Java技术在Web环境中执行并行数据处理程序的关键问题。文章首先介绍了基于Web的Java并行计算的基本概念及其背景,随后详细分析了利用Java进行Web上...
JAVA并行模式JAVA并行模式JAVA并行模式JAVA并行模式JAVA并行模式JAVA并行模式JAVA并行模式
Java8并行流中自定义线程池操作示例 Java8并行流中自定义线程池操作示例主要介绍了Java8并行流中自定义线程池操作,结合实例形式分析了并行流的相关概念、定义及自定义线程池的相关操作技巧。 1. 概览 Java8引入了...
Java 并行编程是利用多核处理器或者分布式计算资源来提高程序执行效率的重要技术。在Java 1.7版本中,引入了一套强大的并行框架,使得开发者能够更方便地编写出高效、可扩展的并发应用程序。这个压缩包文件...
Java并行排序(Parallel Sort)是Java集合框架中提供的一种高效的数据排序方法,它利用了多核处理器的优势,通过并行处理技术来提高排序的速度。在这个经典例子中,我们将深入探讨Java并行排序的工作原理、实现方式...
本次的文件标题为“FEKO6.2并行设置与提交任务.pdf”,表明文档内容是关于FEKO6.2版本的并行计算设置以及任务提交流程的教程。并行计算是通过同时使用多台计算机或多个处理器核心来处理任务,能够显著提高计算效率和...
Java 8 是一个重要的 Java 发行版本,引入了许多新特性,其中并行计算是其一大亮点。本示例通过利用Java 8的并行流(Parallel Stream)特性,显著提升了计算效率,具体体现在对1到400亿数列求和的问题上。传统顺序...
【标题】:“Java 并行爬取网页” 在Java编程中,实现并行爬取网页是一种提高效率的有效方法。这通常涉及到多线程或者更高级的并发机制,如Fork/Join框架。在这个项目中,开发者在Eclipse集成开发环境中编写了一个...
java并行计算 JAVA的MPI---MPJ java并行计算 JAVA的MPI---MPJ java并行计算 JAVA的MPI---MPJ java并行计算 JAVA的MPI---MPJ java并行计算 JAVA的MPI---MPJ
在Java编程语言中,实现并行计算圆周率是一项挑战性的任务,但通过利用多线程和适当的算法,我们可以大大提高计算效率。在这个项目中,我们关注的是如何在4个线程的状态下,3分钟内计算出圆周率的第62到63万位小数。...
数据流Java并行程序设计模型的设计、实现及运行时优 数据流Java并行程序设计模型是指基于数据流多态语言特征设计的一种Java并行程序设计模型。该模型的设计思想源于传统工作中单个处理器的工作性能提升方法的不足。...
<<java并行编程>>英文版chm格式,英文名称<Java Concurrency in Practice>,一直想买这本书,但总是缺货,找到了电子版,分享给大家。 Java Concurrency in Practice By Brian Goetz, Tim Peierls, Joshua Bloch,...
Java 8 是一个重要的 Java 发行版本,引入了许多新特性,其中之一就是并行处理能力的增强,这...在实际开发中,合理使用并行流可以优化代码,提高软件的响应速度,尤其在大数据处理和高性能计算领域有着广泛的应用。
Java核心技术笔记涵盖了许多Java编程的关键知识点,以下是这些主题的详细说明: 1. **面向对象技术**:面向对象编程(OOP)是Java的核心概念。它包括类、对象、封装、继承、多态等核心概念。类是对象的蓝图,定义了...
在Java平台上,多线程和并行计算是两个关键的概念,它们对于开发高效、响应迅速的应用程序至关重要。本文将深入探讨这两个主题,旨在提供全面的知识点解析。 **一、Java多线程** 1. **线程定义**:线程是程序执行...
并行计算框架的Java实现是现代软件开发中的一个重要领域,特别是在大数据处理、机器学习和高性能计算等场景下。本系列的第二部分将深入探讨如何利用Java语言构建并行计算框架,以提高程序的运行效率。在本文中,我们...
在这个“pi.rar_PI_java”压缩包中,包含了一个用Java实现的并行计算实验,目的是通过并行计算来求解π(圆周率)的值。 π的计算通常涉及复杂的数学算法,例如蒙特卡洛方法,这是一种基于概率统计的数值计算方法。...