ExecutorService 线程池及 Callable, Future, CompletableFuture

本文介绍了Java并发编程的基础概念,包括Callable接口和Future接口的使用,以及如何通过ExecutorService执行多线程任务。此外,还详细讲解了ThreadPoolExecutor线程池的配置与管理,ScheduledThreadPoolExecutor的使用方法,以及如何处理任务超载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Callable<V>

java.lang.Callable<V>

它是一个泛型接口,有 V call() 方法,用于 具有返回值的多线程任务

Future<V>

java.util.concurrent.Future<V>
Future对象代表着一个异步操作的结果。

  •  boolean isDone(), 调用此对象的isDone()方法来查询任务是否已完成,它是异步的。
  •  V get(). 调用get()方法获取线程执行结果,它是同步的,在结果准备就绪前一直阻塞。

这两个接口通常和 <T> Future<T> ExecutorService#submit(Callable<T> task) 连用.

CompletableFuture<T>

Future 的子类.

Future 虽然可以拿到异步执行的状态和结果,但是它 没有在任务完成时提供主动的通知回调机制. 此时, 若想判断任务有无完成,  

1. 要么使用阻塞,在future.get()的地方等待future返回的结果,这时又变成同步操作;

2. 要么使用isDone()轮询地判断Future是否完成,这样会耗费CPU的资源.

 

class CompletableFuture<T> implements Future<T>, CompletionStage<T> 
 

ExecutorService 接口

java.util.concurrent.ExecutorService

接口。用来设置线程池并执行多线程任务。它有以下几个方法。

<T> Future<T> submit(Callable<T> task)
提交一个有返回值的任务并运行。在任务成功执行完毕之前,future.get()会阻塞。

void java.util.concurrent.ExecutorService.shutdown()
启动一个有序的关闭,关闭那些先前提交过的已执行完毕的任务。此时ExecutorService不再接受新的任务。

List<Runnable> java.util.concurrent.ExecutorService.shutdownNow()
尝试终止正在执行的任务,终止等待执行的线程,返回等待执行的线程列表。

boolean java.util.concurrent.ExecutorService.isTerminated()

进程池已经被shutdown且所有任务均已完成时,返回true。

Executors工厂类创建ExecutorService对象

java.util.concurrent.Executors

工厂类,可以通过静态方法获得实现ExecutorService接口的对象。

表2-1 常见的ExecutorService实现类

2.1 ThreadPoolExecutor

ExecutorService java.util.concurrent.Executors.newCachedThreadPool()
返回的是java.util.concurrent.ThreadPoolExecutor对象。

java.util.concurrent.ThreadPoolExecutor

类。用于接收提交的任务,放到线程池中运行。

java.util.concurrent.ThreadPoolExecutor.ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

构造函数。

corePoolSize:最小线程数。一般会取Runtime.getRuntime().availableProcessors()。
maximumPoolSize:任务变多时,最大线程数。一般会取corePoolSize*20.
keepAliveTime:多开的线程用完后,等待一定时间再被回收。
unit:时间单位。
workQueue:当线程池已满,新任务不能立即执行的时候,就会放进此等待队列。
threadFactory:创建线程的工厂。
java.util.concurrent.ThreadPoolExecutor.ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)

ThreadPoolExecutor构造函数的重载。

 long java.util.concurrent.ThreadPoolExecutor.getCompletedTaskCount()
返回执行完毕的任务数,是近似值。
 long java.util.concurrent.ThreadPoolExecutor.getTaskCount()
返回加入执行计划的所有任务总数,是近似值。
 int java.util.concurrent.ThreadPoolExecutor.getActiveCount()
 返回正在执行任务的的活动状态的线程数,是近似值。

java.util.concurrent.ThreadFactory
接口,它只有下面一个方法:
Thread java.util.concurrent.ThreadFactory.newThread(Runnable r)
生成Thread并返回。

2.2 ScheduledThreadPoolExecutor

java.util.concurrent.ScheduledThreadPoolExecutor.ScheduledThreadPoolExecutor(int corePoolSize)
构造函数,创建“计划线程池执行器”。此类为ExecutorService的实现类。

ScheduledFuture<?> java.util.concurrent.ScheduledExecutorService.scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
开辟新线程执行任务。延迟initialDelay时间后开始执行command,并且按照period时间周期性重复调用,并且保证在上次运行完后才会执行下一次,周期时间不包括command运行时间。

ScheduledFuture<?> java.util.concurrent.ScheduledExecutorService.scheduleAtFixedRate(Runnable command, long initialDelay, long delay, TimeUnit unit)

延迟initialDelay时间后开始执行command,并且按照period时间周期性重复调用。周期时间包括command运行时间,如果周期时间比command运行时间短,则command运行完毕后,立刻重复运行。

任务中抛出未被捕获的异常不会造成线程池的线程消失。线程池对此做了保护机制。查看jdk源码可以找到这部分代码。

3. 例子

//: concurrency/CallableDemo.java
import java.util.concurrent.*;
import java.util.*;

class TaskWithResult implements Callable {
  private int id;
  public TaskWithResult(int id) {
    this.id = id;
  }
  public String call() throws InterruptedException {
	  TimeUnit.SECONDS.sleep(2);
    return "result of TaskWithResult " + id;
  }
}

public class CallableDemo {
  public static void main(String[] args) {
    ExecutorService exec = Executors.newCachedThreadPool();
    ArrayList> results =
      new ArrayList>();
    for(int i = 0; i < 5; i++)
      results.add(exec.submit(new TaskWithResult(i)));
    for(Future fs : results)
      try {
        // get() blocks until completion:
    	System.out.println(fs.isDone());
        System.out.println(fs.get());
      } catch(InterruptedException e) {
        System.out.println(e);
        return;
      } catch(ExecutionException e) {
        System.out.println(e);
      } finally {
        exec.shutdown();
      }
  }
} /* Output:
false
result of TaskWithResult 0
true
result of TaskWithResult 1
true
result of TaskWithResult 2
true
result of TaskWithResult 3
true
result of TaskWithResult 4
*/
 
 

4.任务超载

interface java.util.concurrent.RejectedExecutionHandler
接口,它只有下面一个方法:
void rejectedExecution(Runnable r, ThreadPoolExecutor executor)
当提交的任务不能被ThreadPoolExecutor执行时(如等待队列已满),调用此函数。

java.util.concurrent.ThreadPoolExecutor.AbortPolicy
RejectedExecutionHandler的实现类。它会抛出异常RejectedExecutionException。
java.util.concurrent.ThreadPoolExecutor.DiscardPolicy
RejectedExecutionHandler的实现类。它的函数体为空,即什么也不做。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值