线程池中CompletionService的应用
来源:互联网 发布:淘宝 新店扶持 编辑:程序博客网 时间:2024/05/29 15:59
当使用ExecutorService启动了多个Callable后,每个Callable会产生一个Future,我们需要将多个Future存入一个线性表,用于之后处理数据。当然,还有更复杂的情况,有5个生产者线程,每个生产者线程都会创建任务,所有任务的Future都存放到同一个线性表中。另有一个消费者线程,从线性表中取出Future进行处理。
CompletionService正是为此而存在,它是一个更高级的ExecutorService,它本身自带一个线程安全的线性表,无需用户额外创建。它提供了2种方法从线性表中取出结果,poll()是非阻塞的,若目前无结果,返回一个null,线程继续运行不阻塞。take()是阻塞的,若当前无结果,则线程阻塞,直到产生一个结果,被取出返回,线程才继续运行。
public class Test {public static void main(String[] args) throws InterruptedException, ExecutionException {ExecutorService executor = Executors.newCachedThreadPool();CompletionService<Integer> comp = new ExecutorCompletionService<>(executor);for(int i = 0; i<5; i++) {comp.submit(new Task());}executor.shutdown();int count = 0, index = 1;while(count<5) {Future<Integer> f = comp.poll();if(f == null) {System.out.println(index + " 没发现有完成的任务");}else {System.out.println(index + "产生了一个随机数: " + f.get());count++;}index++;TimeUnit.MILLISECONDS.sleep(500);}}}class Task implements Callable<Integer> {@Overridepublic Integer call() throws Exception {Random rand = new Random();TimeUnit.SECONDS.sleep(rand.nextInt(7));return rand.nextInt();}}
实际运用小案例:
模拟页面渲染
package com.thread;import java.util.ArrayList;import java.util.List;import java.util.Random;import java.util.concurrent.Callable;import java.util.concurrent.CompletionService;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorCompletionService;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;/** * CompletionService的运用:当Executor遇见BlockingQueue时使用。 * 使用场景: * 如果向Executor提交了一个批处理任务,并且希望在他们完成后获得结果。 * * CompletionService整合了Executor和BlockingQueue的功能,你可以将Callable任务提交给它执行, * 然后使用类似队列中的take和poll方法,在结果完整可用时(只是等待任意一个future的返回值),获得这个结果。就像一个大包的Future。 * * completionService.take()的说明是:检索并移除已完成的任务,如果没有任何一个任务完成的,则继续等待 * * 从案例的结果可以看出,每当图片下载完毕后,就会执行渲染操作。 * take方法只是检索completionService中所有future,看是否有执行完的任务,并获得结果。 * * @author hadoop * */public class CompletionThread {static ExecutorService mExecutor = Executors.newFixedThreadPool(5);static int totalTimeDownPhoto =0;/** * 模拟页面渲染场景 */static void renderPage(){ final List<String> info = new ArrayList<String>(); for (int i = 0; i < 20; i++) { info.add("图片" + i); } CompletionService<String> completionService = new ExecutorCompletionService<String>(mExecutor); /** * 开启多线程处理下载图片的任务 */ for(final String str : info){ completionService.submit(new Callable<String>() {@Overridepublic String call() throws Exception {//下载图片download(str)int randomTime = new Random().nextInt(9) + 1;//限制耗时不会出现0s,不会大于10sThread.sleep(randomTime*1000);System.out.println("下载" + str +"耗费了" + randomTime + "s");computeTime(randomTime);return str;} }); } try { System.out.println("处理文字渲染的逻辑"); int randomTime = new Random().nextInt(9) + 1;Thread.sleep(1000*randomTime);computeTime(randomTime);System.out.println("处理文字渲染的逻辑耗费了" + randomTime + "s");/** * 如果渲染图片耗时也比较久,也可以使用多线程。这里只是模拟,没有使用多线程处理渲染图片的过程 */for (int i = 0; i < info.size(); i++) { //take检索并移除已完成的任务,如果没有任何一个任务完成的,则继续等待 Future<String> f = completionService.take(); //处理渲染图片的逻辑 randomTime = new Random().nextInt(3) + 1; Thread.sleep(1000*randomTime); computeTime(randomTime); System.out.println("渲染"+f.get() +"耗时"+randomTime+"s"); }} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();} /** * 只有执行了shutdown方法,执行isTerminated才有效。否则isTerminated一直为ture */ mExecutor.shutdown(); while(true){if(mExecutor.isTerminated()){System.out.println("所有任务都执行完了,关闭线程池");break;}}}/** * 统计下载图片所花费的总时间 * @param randomTime */static void computeTime(int randomTime){synchronized (mExecutor) {totalTimeDownPhoto += randomTime;}}public static void main(String[] args) {long start = System.currentTimeMillis();renderPage();long end = System.currentTimeMillis();System.out.println("渲染页面总耗时:"+(end - start));System.out.println("下载每张图片,渲染每张图片以及渲染文字的合计耗时是:"+ totalTimeDownPhoto);int saveTime = (int) (totalTimeDownPhoto - (end - start)/1000);System.out.println("总节约时间:"+ saveTime+"s");}}
0 0
- 线程池中CompletionService的应用
- Java线程池CompletionService的简单应用
- 线程池原理(五):CompletionService
- Java:多线程,线程池,使用CompletionService通过Future来处理Callable的返回结果
- 多线程,线程池,使用CompletionService通过Future来处理Callable的返回
- Java:多线程,线程池,使用CompletionService通过Future来处理Callable的返回结果
- Java线程之CompletionService
- Java线程之CompletionService
- Java线程 CompletionService
- 创建线程的第三种方式Callable和Future CompletionService
- 线程池实现,并通过CompletionService,来实现反馈处理
- 多线程Demo-CompletionService收集线程池执行结果
- 关于事务、ThreadLocal应用、CompletionService的一些总结
- JDK1.5中线程池的应用。
- C#中线程池的简单应用
- Spring中线程池的应用
- Galley2中线程池的应用
- Java/Android中线程池的应用
- POJ 3687 拓扑排序
- 1. Two Sum
- nginx https 跳转方法
- mysql基本操作
- [IO]——编码和解码
- 线程池中CompletionService的应用
- 字符串转成整数大数乘法
- 说说JSON和JSONP,也许你会豁然开朗
- 关于string函数族实现的准备
- 计算几何----判断点是否在一个矩形内
- [你必须知道的.NET]第三十五回,判断dll是debug还是release,这是个问题
- [IO]——指定字符集
- C++实验3-本月有几天?
- [JAVA · 初级]:21.多线程