Java并发编程之CompletionService

60 篇文章 2 订阅
12 篇文章 0 订阅

简介:CompletionService功能是以异步的方式一边生成新任务,一边处理完成的任务,使得任务的执行与处理进行分离。使用submit提交任务,使用task获取已经完成的任务

先看个示例:

此功能是获取每个任务的执行结果,这里通过future来实现

public class FutureDemo {
	
	private static class CallableTask implements Callable<String> {

		private int time;
		private String name ;
		public CallableTask(int time, String name) {
			this.time = time ;
			this.name = name ;
		}
		
		@Override
		public String call() throws Exception {
			TimeUnit.SECONDS.sleep(this.time) ;
			return name ;
		}
		
	}
	
	public static void main(String[] args) throws Exception {
		ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(20)) ;
		List<Callable<String>> tasks = new ArrayList<>() ;
		List<Future<String>> results = new ArrayList<>() ;
		for (int i = 1; i <= 5; i++) {
			tasks.add(new CallableTask(i, "name" + i)) ;
		}
		for (int i = 0; i < 5; i++) {
			results.add(pool.submit(tasks.get(i))) ;
		}
		for (int i = 4; i >= 0; i--) {
			System.out.println(results.get(i).get()) ;
		}
	}
	
}

执行结果:

Java并发编程之CompletionService

 

这里提交了5个任务,分别等待1到5秒的时间,在获取任务执行结果的时候,不管哪个任务先执行都只会按照你的获取顺序去获取即便是有其它的任务已经先执行完。future具有阻塞功能。

接下来用CompletionService实现:

public class CompletionServiceDemo {
	
	private static class CallableTask implements Callable<String> {

		private int time;
		private String name ;
		public CallableTask(int time, String name) {
			this.time = time ;
			this.name = name ;
		}
		
		@Override
		public String call() throws Exception {
			TimeUnit.SECONDS.sleep(this.time) ;
			return name ;
		}
		
	}
	
	public static void main(String[] args) throws Exception {
		ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(20)) ;
		List<Callable<String>> tasks = new ArrayList<>() ;
		CompletionService<String> cs = new ExecutorCompletionService<>(pool) ;
		for (int i = 1; i <= 5; i++) {
			tasks.add(new CallableTask(i, "name" + i)) ;
		}
		for (int i = 0; i < 5; i++) {
			cs.submit(tasks.get(i)) ;
		}
		for (int i = 4; i >= 0; i--) {
			System.out.println("--") ;
			System.out.println(cs.take().get()) ;
		}
	}
	
}

执行结果:

Java并发编程之CompletionService

 

运行结果发现哪个任务先执行完take就会获取那个任务,当没有任务完成的时候take会阻塞。


CompletionService的poll方法非阻塞的,poll方法获取并删除已经完成的Future,如果没有就返回

null。

public class CompletionServiceDemo2 {
	
	private static class CallableTask implements Callable<String> {

		private int time;
		private String name ;
		public CallableTask(int time, String name) {
			this.time = time ;
			this.name = name ;
		}
		
		@Override
		public String call() throws Exception {
			TimeUnit.SECONDS.sleep(this.time) ;
			return name ;
		}
		
	}
	
	public static void main(String[] args) throws Exception {
		ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(20)) ;
		CompletionService<String> cs = new ExecutorCompletionService<>(pool) ;
		for (int i = 0; i < 5; i++) {
			cs.submit(new CallableTask(i, "name" + i)) ;
		}
		for (int i = 4; i >= 0; i--) {
			System.out.println(cs.poll()) ;
		}
	}
	
}

执行结果:

Java并发编程之CompletionService

 

获取到了第一个完成的任务,其它的都返回了null。

poll返回还可以设置超时时间

public static void main(String[] args) throws Exception {
		ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(20)) ;
		CompletionService<String> cs = new ExecutorCompletionService<>(pool) ;
		for (int i = 0; i < 5; i++) {
			cs.submit(new CallableTask(i, "name" + i)) ;
		}
		for (int i = 4; i >= 0; i--) {
			System.out.println(cs.poll(5, TimeUnit.SECONDS)) ;
		}
	}

这里超时设置了5秒钟,如果在5秒内获取到了数据那就继续向下执行,如果超过了5秒也会继续向下执行。


CompletionService异常处理

示例:

public class CompletionServiceDemo3 {
	
	private static class CallableTask implements Callable<String> {

		private int time;
		private String name ;
		public CallableTask(int time, String name) {
			this.time = time ;
			this.name = name ;
		}
		
		@Override
		public String call() throws Exception {
			if (this.time == 2) {
				throw new RuntimeException("发生了异常:" + this.name) ;
			}
			TimeUnit.SECONDS.sleep(this.time) ;
			return name ;
		}
		
	}
	
	public static void main(String[] args) throws Exception {
		ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(20)) ;
		CompletionService<String> cs = new ExecutorCompletionService<>(pool) ;
		for (int i = 0; i < 5; i++) {
			cs.submit(new CallableTask(i, "name" + i)) ;
		}
		for (int i = 4; i >= 0; i--) {
			System.out.println(cs.take()) ;
		}
	}
	
}

这里设置了当time为2时抛出异常,执行结果:

Java并发编程之CompletionService

 

在这里获取结果的时候只是调用了take,并没有调用get方法获取值信息,所以这里跟没有异常一样没有反应出来。

获取返回值时:

public static void main(String[] args) throws Exception {
		ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(20)) ;
		CompletionService<String> cs = new ExecutorCompletionService<>(pool) ;
		for (int i = 0; i < 5; i++) {
			cs.submit(new CallableTask(i, "name" + i)) ;
		}
		for (int i = 4; i >= 0; i--) {
			System.out.println(cs.take().get()) ;
		}
	}

执行结果:

Java并发编程之CompletionService

 

当调用了cs.take().get()返回值时异常才抛出。从这也发现当有异常抛出时,其它还任务都将被终止运行。


CompletionService.submit(Runnable, V)指定返回值(当执行成功)

public class CompletionServiceDemo3 {
	
	private static class User {
		public String name ;
	}
	
	private static class Task implements Runnable {
		private User user ;
		public Task(User user) {
			this.user = user ;
		}
		@Override
		public void run() {
			try {
				TimeUnit.SECONDS.sleep(5) ;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}			
			System.out.println("任务执行完成。。。") ;
			this.user.name = "张三" ;
		}
		
	}
	
	public static void main(String[] args) throws Exception {
		ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(20)) ;
		CompletionService<User> cs = new ExecutorCompletionService<>(pool) ;
		User user = new User() ;
		Future<User> f = cs.submit(new Task(user), user) ;
		System.out.println(f.get().name) ;
	}
	
}

执行结果:

Java并发编程之CompletionService

 

完毕!!!

给个关注+转发呗,谢谢

Oracle数据同步到Elasticsearch

spring data jpa 高级应用

Spring Cloud Sentinel 流控限流

Spring MVC 异常处理方式

Spring MVC 异步请求方式

Spring Cloud Sentinel 熔断降级

Spring Cloud Sentinel 基础配置

SpringCloud Nacos 整合feign

SpringMVC参数统一验证方法

Springboot Security 基础应用 (1)

SpringBoot多数据源配置详解

springboot mybatis jpa 实现读写分离

Spring Cloud Sentinel 热点参数限流

SpringBoot开发自己的Starter

SpringCloud Hystrix实现资源隔离应用

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值