跳转至

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 区别

CallableRunnable接口是Java中用于定义并发任务的两个核心接口,它们之间有以下几个区别:

  1. 返回结果:Runnable接口的run()方法没有返回值,而Callable接口的call()方法可以返回一个结果。

  2. 异常处理:Runnable接口的run()方法不能抛出任何受检异常,只能通过捕获异常并在方法内部处理。而Callable接口的call()方法可以抛出受检异常,需要使用者进行适当的异常处理。

  3. 使用方式:Runnable通常用于执行一些没有返回结果的异步任务,而Callable则通常用于执行需要返回结果的异步任务。

  4. 线程池的submit方法:线程池的submit()方法接受Runnable任务时,返回一个Future对象,该对象用于表示任务的异步执行结果,但该对象的get()方法返回的结果始终为null。当提交Callable任务时,submit()方法返回的Future对象可以通过get()方法获取任务的执行结果。

综上所述,Runnable适用于不需要返回结果的简单异步任务,而Callable适用于需要返回结果的复杂异步任务。在使用线程池时,可以根据任务的需求选择使用RunnableCallable