ExecutoreService增加了生命周期的管理,有三种状态:运行、关闭、已终止。
public class LifecycleWebServer { private final ExecutorService exec = Executors.newCachedThreadPool(); public void start() throws IOException { ServerSocket socket = new ServerSocket(80); while (!exec.isShutdown()) { try { final Socket conn = socket.accept(); exec.execute(new Runnable() { public void run() { handleRequest(conn); } }); } catch (RejectedExecutionException e) { if (!exec.isShutdown()) log("task submission rejected", e); } } } public void stop() { exec.shutdown(); } private void log(String msg, Exception e) { Logger.getAnonymousLogger().log(Level.WARNING, msg, e); } void handleRequest(Socket connection) { Request req = readRequest(connection); if (isShutdownRequest(req)) stop(); else dispatchRequest(req); } interface Request { } private Request readRequest(Socket s) { return null; } private void dispatchRequest(Request r) { } private boolean isShutdownRequest(Request r) { return false; } }
6.2.5 延迟任务和周期任务
我们通常会用Timer管理延迟或周期执行的一些任务,但是这是不安全的,因为Timer存在一些缺陷,我们应该考虑使用ScheduledThreadPoolExecutor来代替它,可以通过ScheduledThreadPoolExecutor构造函数或者是newScheduledThreadPool工厂方法创建该类的对象。
6.3.2 携带结果的任务Callable和Future
Executor执行的任务有4个生命周期阶段:创建、提交、开始、完成。如果想要取消某些任务,在Executor框架中,已提交但尚未开始的任务可以取消,但对于那些已经开始执行的任务,只有当它们能响应中断时,才能取消。
Future表示一个任务的生命周期,并提供了相应的方法判断是否已经完成或取消,以及获取任务的结果和取消任务等。
ExecutorService中所有submit方法都将返回一个Future,从而将一个Runnable或Callable提交给Executor,并得到一个Future用来获取任务执行结果或者取消任务。还可以显示为某个指定的Runnable或者Callable实例化一个FutureTask。
6.3.5 CompletionService:Executor与BlockingQueue
如果向Executor提交了一组计算任务,并且希望在计算完成后获得结果,那么可以保留与每个任务关联的Futrue,然后反复使用get方法,同时将参数timeout指定为0,从而通过轮训来判断任务是否完成,这个太繁琐的。我们可以通过CompletionService优化这种方案。
示例:使用CompletionService实现页面渲染器:
public abstract class Renderer { private final ExecutorService executor; Renderer(ExecutorService executor) { this.executor = executor; } void renderPage(CharSequence source) { final List<ImageInfo> info = scanForImageInfo(source); CompletionService<ImageData> completionService = new ExecutorCompletionService<ImageData>(executor); for (final ImageInfo imageInfo : info) completionService.submit(new Callable<ImageData>() { public ImageData call() { return imageInfo.downloadImage(); } }); renderText(source); try { for (int t = 0, n = info.size(); t < n; t++) { Future<ImageData> f = completionService.take(); ImageData imageData = f.get(); renderImage(imageData); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (ExecutionException e) { throw launderThrowable(e.getCause()); } } interface ImageData { } interface ImageInfo { ImageData downloadImage(); } abstract void renderText(CharSequence s); abstract List<ImageInfo> scanForImageInfo(CharSequence s); abstract void renderImage(ImageData i); }
6.3.7 为任务设置时限:
public class RenderWithTimeBudget { private static final Ad DEFAULT_AD = new Ad(); private static final long TIME_BUDGET = 1000; private static final ExecutorService exec = Executors.newCachedThreadPool(); Page renderPageWithAd() throws InterruptedException { long endNanos = System.nanoTime() + TIME_BUDGET; Future<Ad> f = exec.submit(new FetchAdTask()); // Render the page while waiting for the ad Page page = renderPageBody(); Ad ad; try { // Only wait for the remaining time budget long timeLeft = endNanos - System.nanoTime(); ad = f.get(timeLeft, NANOSECONDS); } catch (ExecutionException e) { ad = DEFAULT_AD; } catch (TimeoutException e) { ad = DEFAULT_AD; f.cancel(true); } page.setAd(ad); return page; } Page renderPageBody() { return new Page(); } static class Ad { } static class Page { public void setAd(Ad ad) { } } static class FetchAdTask implements Callable<Ad> { public Ad call() { return new Ad(); } } }
6.3.8 还有一个很好用的invokeAll方法
支持限时的invokeAll,将多个任务提交到一个ExecutorService得到结果。invokeAll方法参数为一组任务,并返回一组Future。这两个集合有着相同的结构。invokeAll按照任务集合中迭代器顺序将所有Future添加到返回集合中,从而使调用者能将各个Future与其表示的Callable关联起来。当所以任务都执行完成时,或者调用线程中断,或者超时,invokeAll将返回。当超过指定时限后,任何未完成任务都将取消。
用一个限时报价服务来阐明:
public class TimeBudget { private static ExecutorService exec = Executors.newCachedThreadPool(); public List<TravelQuote> getRankedTravelQuotes(TravelInfo travelInfo, Set<TravelCompany> companies, Comparator<TravelQuote> ranking, long time, TimeUnit unit) throws InterruptedException { List<QuoteTask> tasks = new ArrayList<QuoteTask>(); for (TravelCompany company : companies) tasks.add(new QuoteTask(company, travelInfo)); List<Future<TravelQuote>> futures = exec.invokeAll(tasks, time, unit); List<TravelQuote> quotes = new ArrayList<TravelQuote>(tasks.size()); Iterator<QuoteTask> taskIter = tasks.iterator(); for (Future<TravelQuote> f : futures) { QuoteTask task = taskIter.next(); try { quotes.add(f.get()); } catch (ExecutionException e) { quotes.add(task.getFailureQuote(e.getCause())); } catch (CancellationException e) { quotes.add(task.getTimeoutQuote(e)); } } Collections.sort(quotes, ranking); return quotes; } } class QuoteTask implements Callable<TravelQuote> { private final TravelCompany company; private final TravelInfo travelInfo; public QuoteTask(TravelCompany company, TravelInfo travelInfo) { this.company = company; this.travelInfo = travelInfo; } TravelQuote getFailureQuote(Throwable t) { return null; } TravelQuote getTimeoutQuote(CancellationException e) { return null; } public TravelQuote call() throws Exception { return company.solicitQuote(travelInfo); } } interface TravelCompany { TravelQuote solicitQuote(TravelInfo travelInfo) throws Exception; } interface TravelQuote { } interface TravelInfo { }
本人博客已搬家,新地址为:http://yidao620c.github.io/
相关推荐
在现代Java应用开发中,多线程并发编程已成为提升程序性能的关键技术之一。Java通过引入Executor框架,为并发任务的执行提供了一种高效、灵活的管理机制。本文将深入探讨Executor框架的设计哲学、核心组件,并结合...
《Java并发编程实战》是Java并发编程领域的一本经典著作,它深入浅出地介绍了如何在Java平台上进行高效的多线程编程。这本书的源码提供了丰富的示例,可以帮助读者更好地理解书中的理论知识并将其应用到实际项目中。...
## Java并发编程与Executor框架 随着计算机硬件技术的发展,现代CPU通常都是多核的,这为软件提供了并行计算的能力。Java的并发编程模型在这样的背景下变得尤为重要。为了简化多线程编程,Java标准库提供了`java....
《Java并发编程的艺术》这本书是Java开发者深入理解并发编程的重要参考书籍。这本书全面地介绍了Java平台上的并发和多线程编程技术,旨在帮助开发者解决在实际工作中遇到的并发问题,提高程序的性能和可伸缩性。 ...
Java并发编程中的Executor、Executors和ExecutorService是Java并发编程框架的重要组成部分,它们为开发者提供了高效管理和控制线程执行的工具。以下是对这些概念的详细解释: 1. Executor: Executor是一个接口,它...
根据提供的信息,“Java 并发编程实战.pdf”这本书聚焦于Java并发编程的实践与应用,旨在帮助读者深入了解并掌握Java中的多线程技术及其在实际项目中的应用技巧。虽然部分内容未能提供具体章节或实例,但从标题及...
《JAVA并发编程艺术》是Java开发者深入理解和掌握并发编程的一本重要著作,它涵盖了Java并发领域的核心概念和技术。这本书详细阐述了如何在多线程环境下有效地编写高效、可靠的代码,对于提升Java程序员的技能水平...
《Java并发编程从入门到精通》是一本专为Java开发者设计的深度学习并发编程的书籍。作者韩剑锋,凭借其12年的IT行业经验,曾担任多家IT公司的研发总监和技术总监,以其丰富的实战经验和深厚的理论知识,为读者提供了...
Java并发编程是软件开发中的一个关键领域,尤其是在大型企业级应用和分布式系统中。通过学习相关的书籍,开发者可以深入理解如何有效地设计和实现高效的多线程应用程序,避免并发问题,如竞态条件、死锁、活锁等。...
Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。这份“java并发编程内部分享PPT”显然是一个深入探讨这一主题的资料,旨在帮助开发者...
### Java 并发核心编程知识点解析 #### 一、Java并发概述 自Java诞生之初,其设计者就赋予了该语言强大的并发处理能力。Java语言内置了对线程和锁的支持,这...理解和掌握这些概念和技术是成功进行并发编程的关键。
《Java并发编程的艺术》内容涵盖Java并发编程机制的底层实现原理、Java内存模型、Java并发编程基础、Java中的锁、并发容器和框架、原子类、并发工具类、线程池、Executor框架等主题,每个主题都做了深入的讲解,同时...
6. **线程池**:Executor框架是Java并发编程的重要组成部分,讲解ThreadPoolExecutor的使用,包括线程池的参数配置、工作队列的选择以及线程池的生命周期管理。 7. **死锁与活锁**:分析可能导致线程死锁的原因,...
### Java并发编程实践 #### 书籍概述 《Java并发编程实践》是一本由Brian Goetz等人编写的关于Java并发编程的经典著作。本书深入浅出地介绍了Java 5.0及之后版本中新增加的并发特性,并对并发编程进行了全面而详尽...
6.2 Executor框架 6.2.1 示例:基于Executor的Web服务器 6.2.2 执行策略 6.2.3 线程池 6.2.4 Executor的生命周期 6.2.5 延迟任务与周期任务 6.3 找出可利用的并行性 6.3.1 示例:串行的页面渲染器 6.3.2 ...
#### 四、Java并发编程最佳实践 ##### 4.1 减少锁的竞争 在设计并发程序时,应尽可能减少锁的使用范围和时间,避免过度锁定。例如,可以通过分解任务、优化数据结构等方式减少锁的竞争。 ##### 4.2 使用线程本地...
Java并发编程是软件开发中的重要领域,特别是在大型系统和高并发场景中不可或缺。"13-Java并发编程学习宝典.zip" 包含了一系列关于Java并发编程的学习资源,旨在帮助开发者掌握多线程编程的核心技术和最佳实践。以下...
Java并发编程是Java开发者必须掌握的关键技能之一,尤其是在多核处理器和分布式系统广泛使用的今天。以下是对标题和描述中提及的两本经典书籍——《Concurrent Programming in Java》和《Java Concurrency in ...