浅析Java CompletionService
JDK的CompletionService提供了一种将生产新的异步任务与使用已完毕任务的结果分离开来的服务。生产者 submit 运行的任务。使用者 take 已完毕的任务,并依照完毕这些任务的顺序处理它们的结果。比如,CompletionService 能够用来管理异步 IO 。运行读操作的任务作为程序或系统的一部分提交,然后。当完毕读操作时,会在程序的不同部分运行其它操作,运行操作的顺序可能与所请求的顺序不同。
举个样例:如今要向server发送HTTP请求。服务端对于每一个请求都须要做非常多额外操作,非常消耗时间,则能够将每一个请求接受之后。提交到CompletionService异步处理,等运行完毕之后,在返回给client
package com.yf.concurrent;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CompletionServiceTest {
	private ExecutorService threadPool = Executors.newCachedThreadPool();
	private CompletionService<Response> completionService = new ExecutorCompletionService<Response>(
			Executors.newCachedThreadPool());
	public CompletionServiceTest() {
		new Thread() {
			public void run() {
				while (true) {
					try {
						Future<Response> f = completionService.take();
						/**
						 * 获取响应信息,返回给client
						 * 假设completionService任务队列为空,此处将堵塞
						 */
						Response resp = f.get();
						System.out.println(resp.getId());
					} catch (Exception e) {
						System.out.println("Exception happened:"+e.getMessage());
					}
				}
			};
		}.start();
	}
	class Request{
		private int rid;
		private String body;
		public int getRid() {
			return rid;
		}
		public void setRid(int rid) {
			this.rid = rid;
		}
		public String getBody() {
			return body;
		}
		public void setBody(String body) {
			this.body = body;
		}
	}
	class Response {
		private int id;
		private String body;
		public int getId() {
			return id;
		}
		public void setId(int id) {
			this.id = id;
		}
		public String getBody() {
			return body;
		}
		public void setBody(String body) {
			this.body = body;
		}
	}
	class HTTPExecutor {
		public Future<Response> execute(final Request request) {
			Future<Response> f = threadPool.submit(new Callable<Response>() {
				public Response call() throws Exception {
					Response response = new Response();
					Thread.currentThread().sleep(3000);
					response.setId(request.getRid());
					response.setBody("response");
					return response;
				}
			});
			return f;
		}
	}
	public void submitHTTP(final Request request) {
		completionService.submit(new Callable<Response>() {
			public Response call() throws Exception {
				return new HTTPExecutor().execute(request).get();
			}
		});
	}
	public static void main(String[] args) {
		CompletionServiceTest t = new CompletionServiceTest();
		for (int i = 0; i < 10; i++) {
			/**
			 * 发送10个HTTP请求
			 */
			Request request =t.new Request();
			request.setRid(i);
			request.setBody("request");
			t.submitHTTP(request);
		}
	}
}
能够简单查看一下CompletionService的唯一实现类ExecutorCompletionService源代码
关键代码例如以下:
public ExecutorCompletionService(Executor executor) {
        if (executor == null)
            throw new NullPointerException();
        this.executor = executor;
        this.aes = (executor instanceof AbstractExecutorService) ?
            (AbstractExecutorService) executor : null;
        this.completionQueue = new LinkedBlockingQueue<Future<V>>();
    }
public ExecutorCompletionService(Executor executor,
                                     BlockingQueue<Future<V>> completionQueue) {
        if (executor == null || completionQueue == null)
            throw new NullPointerException();
        this.executor = executor;
        this.aes = (executor instanceof AbstractExecutorService) ?
(AbstractExecutorService) executor : null;
        this.completionQueue = 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;
    }通过ExecutorCompletionService的构造器可知,CompletionService 依赖于一个单独的 Executor 来实际运行任务。内部管理了一个堵塞队列来,在调用submit方法时。会向创建一个新的RunnableFuture,然后异步运行该RunnableFuture。当其状态变为done后,加入CompletionService的堵塞队列中,外部通过调用take()(堵塞)或者poll()(非堵塞,为空返回null)方法获取运行结果。
浅析Java CompletionService的更多相关文章
- 浅析Java中的final关键字
		浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ... 
- 浅析Java.lang.Process类
		一.概述 Process类是一个抽象类(所有的方法均是抽象的),封装了一个进程(即一个执行程序). Process 类提供了执行从进程输入.执行输出到进程.等待进程完成.检查进程的 ... 
- 浅析Java中的访问权限控制
		浅析Java中的访问权限控制 今天我们来一起了解一下Java语言中的访问权限控制.在讨论访问权限控制之前,先来讨论一下为何需要访问权限控制.考虑两个场景: 场景1:工程师A编写了一个类ClassA,但 ... 
- [转载]浅析Java中的final关键字
		浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ... 
- 浅析JAVA设计模式之工厂模式(一)
		1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ... 
- 浅析java内存管理机制
		内存管理是计算机编程中的一个重要问题,一般来说,内存管理主要包括内存分配和内存回收两个部分.不同的编程语言有不同的内存管理机制,本文在对比C++和Java语言内存管理机制的不同的基础上,浅析java中 ... 
- 【转】浅析Java中的final关键字
		谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法. ... 
- 浅析 java ArrayList
		浅析 java ArrayList 简介 容器是java提供的一些列的数据结构,也可以叫语法糖.容器就是用来装在其他类型数据的数据结构. ArrayList是数组列表所以他继承了数组的优缺点.同时他也 ... 
- [转帖]浅析java程序的执行过程
		浅析java程序的执行过程 转帖来源: https://www.cnblogs.com/wangjiming/p/10315983.html 之前学习过 这一块东西 但是感觉理解的不深刻. copy一 ... 
随机推荐
- mybatis在mysql中的分页扩展
			applicationContext.xml <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlS ... 
- 关于jquery的入门,简单的封装。
			看过不同的博客,觉得以下的博客写的比较简洁明了,通俗易懂. 关于jquery博客:http://www.cnblogs.com/moqiutao/p/6523924.html 关于js:http:// ... 
- Springboot拦截器未起作用
			之前遇到要使用springboot拦截器却始终未生效的状况,查了网上的博客,大抵都是@Component,@Configuration注解未加,或是使用@ComponentScan增加包扫描,但是尝试 ... 
- MQ之如何做到消息幂等 (转 优秀)
			一.缘起 MQ消息必达,架构上有两个核心设计点: (1)消息落地 (2)消息超时.重传.确认 再次回顾消息总线核心架构,它由 发送端.服务端.固化存储.接收端 四大部分组成. 为保证消息的可达性,超时 ... 
- 关于CSRF跨域请求伪造的解决办法
			中秋节时候我们的应用在短信验证码这块被恶意刷单,比如被用来做垃圾短信之类的,如果大规模被刷也能造成不小的损失.这还只是短信验证码,如果重要的API遭到CSRF的攻击,损失不可估量.所以紧急加班解决了C ... 
- 用js获取当前月份的天数
			在获取每月天数的时候,一般都是存储到一个数组中进行获取,但是如果是二月份的话就需要首先判断是否闰年,再确定是28还是29了. js可以通过Date对象很方便的获取到每月的天数,在初始化Date对象时, ... 
- angularjs ui-view多视口多层嵌套路由配置
			最近研究了一下ui-view多层嵌套,整理了一下 1.最简单的ui-view用法 html部分: <ul class="nav navbar-nav"> <li ... 
- redis window 安装测试--记录
			1.下载地址https://github.com/dmajkic/redis/downloads 2.打开一个cmd窗口,使用cd命令切换到指定目录(D:\redis\64bit)运行 redis-s ... 
- 进度条(Progressbar)
			进度条(Progressbar) 提供如下一些样式改变进度条的外观 @android:style/Widget.ProgressBar.Horizontal(水平进度条) @android:style ... 
- linux 光盘yum源搭建
			1.挂载光盘 2.进入 /etc/yum.repos.d 目录,修改其它配置文件后缀名 mv CentOS-Base.repo CentOS-Base.repo.bakmv CentOS-CR.rep ... 
