Concurrent
Java 并发相关
这里记录 java 并发相关知识
CompletionService
功能
Callable+Future
可以实现多个 task 并行执行,但是如果遇到前面的 task 执行较慢时需要阻塞等待前面的 task 执行完后面 task 才能取得结果;CompletionService
的主要功能就是一边生成任务,一边获取任务的返回值。让两件事分开执行,任务之间不会互相阻塞,可以实现先执行完的先取结果,不再依赖任务顺序了 ;- 只有一个实现类:
ExecutorCompletionService
;
应用场景
- 需要批量提交异步任务的时候(
CompletionService
将线程池Executor
和阻塞队列BlockingQueue
的功能融合在了一起,能够让批量异步任务的管理更简单); - 让异步任务的执行结果有序化:先执行完的先进入阻塞队列;
- 线程池隔离
:CompletionService
支持自己创建线程池,这种隔离性能避免几个特别耗时的任务拖垮整个应用的风险;
ExecutorCompletionService
ExecutorCompletionService
是Java中的一个实用工具类,它实现了 CompletionService
接口,用于简化并发任务的管理和结果获取。它结合了线程池和阻塞队列,可以更方便地获取已完成任务的结果。
ExecutorCompletionService
的主要作用是将已完成的任务封装成 Future
对象,这样可以通过获取 Future
对象的方式获取任务的执行结果,而无需手动迭代任务列表来获取结果。
Future<V> submit(Callable<V> task)
: 提交一个Callable类型任务,并返回该任务执行结果关联的Future;Future<V> submit(Runnable task,V result):
提交一个Runnable类型任务,并返回该任务执行结果关联的Future; -Future<V> take()
: 从内部阻塞队列中获取并移除第一个执行完成的任务,阻塞,直到有任务完成;Future<V> poll()
: 从内部阻塞队列中获取并移除第一个执行完成的任务,获取不到则返回null,不阻塞;Future<V> poll(long timeout, TimeUnit unit)
: 从内部阻塞队列中获取并移除第一个执行完成的任务,阻塞时间为timeout,获取不到则返回null;
Callable 与 Runnable 区别
Callable
和Runnable
接口是Java中用于定义并发任务的两个核心接口,它们之间有以下几个区别:
-
返回结果:
Runnable
接口的run()
方法没有返回值,而Callable
接口的call()
方法可以返回一个结果。 -
异常处理:
Runnable
接口的run()
方法不能抛出任何受检异常,只能通过捕获异常并在方法内部处理。而Callable
接口的call()
方法可以抛出受检异常,需要使用者进行适当的异常处理。 -
使用方式:
Runnable
通常用于执行一些没有返回结果的异步任务,而Callable
则通常用于执行需要返回结果的异步任务。 -
线程池的submit方法:线程池的
submit()
方法接受Runnable
任务时,返回一个Future
对象,该对象用于表示任务的异步执行结果,但该对象的get()
方法返回的结果始终为null
。当提交Callable
任务时,submit()
方法返回的Future
对象可以通过get()
方法获取任务的执行结果。
综上所述,Runnable
适用于不需要返回结果的简单异步任务,而Callable
适用于需要返回结果的复杂异步任务。在使用线程池时,可以根据任务的需求选择使用Runnable
或Callable
。