Java线程池ExecutorService中重要的方法

ExecutorService 介绍

image-20210126211305605

ExecutorServicejava线程池定义的一个接口,它在 java.util.concurrent包中,在这个接口中定义了和后台任务执行相关的方法。

image-20210126212202708

Java API对 ExecutorService接口实现有两个,所以这两个即是线程池的具体实现。
1. ThreadPoolExecutor
2. ScheduledThreadPoolExecutor
ExecutorService还继承了 Executor接口。

image-20210126220009540

实线表示继承,需要表示实现

ExecutorService的创建

Java提供了一个工厂类 Executors来创建各种线程池。
  • newCachedThreadPool 创建一个可缓存的线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,如果没有可以回收的,则新建线程。
  • newFixedThreadPool 创建一个定长的线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  • newScheduledThreadPool 创建一个定长线程池,可以定时周期性执行任务。
  • newSingleThreadPool 创建一个单线程线程池,它只会用唯一的线程来执行任务,保证所有任务按照指定顺序来执行(FIFO,LIFO)
Executors是一个工厂类,它所有的方法返回的都是 ThreadPoolExecutorScheduledThreadPoolExecutor这两个类的实例。

ExecutorService的使用

ExecutorService executorService = Executors.newFixedThreadPool(10);

executorService.execute(new Runnable() {
public void run() {
    System.out.println("入门小站");
}
});

executorService.shutdown();

ExecutorService的执行方法

  • execute(Runnable)
  • submit(Runnable)
  • submit(Callable)
  • invokeAny(...)
  • invokeAll(...)

execute(Runnable) 无法获取执行结果

接收一个 Runnable实例,并且异步执行
ExecutorService executorService = Executors.newSingleThreadExecutor();

executorService.execute(new Runnable() {
public void run() {
    System.out.println("Asynchronous task");
}
});

executorService.shutdown();
没有办法获取执行结果。

submit(Runnable) 可以判断任务是否完成

submit(Runnable)execute(Runnable)多返回一个 Future,可以用来判断提交的任务是否执行完成。
Future future = executorService.submit(new Runnable() {
public void run() {
    System.out.println("Asynchronous task");
}
});

future.get();  //returns null if the task has finished correctly.
如果任务完成, future.get()会返回null, future.get会阻塞。

submit(Callable)可以获取返回结果

submit(Callable)和submit(Runnable)类似,也会返回一个Future对象,但是除此之外,submit(Callable)接收的是一个Callable的实现,Callable接口中的call()方法有一个返回值,可以返回任务的执行结果,而Runnable接口中的run()方法是void的,没有返回值
Future future = executorService.submit(new Callable(){
public Object call() throws Exception {
    System.out.println("Asynchronous Callable");
    return "Callable Result";
}
});

System.out.println("future.get() = " + future.get());
如果任务完成, future.get会返回 Callable执行返回的结果,同样 future.get()会阻塞。

invokeAny(...)

invokeAny(...)方法接收的是一个 Callable的集合,执行这个方法不会返回Future,但是会返回所有Callable任务中其中一个任务的执行结果。这个方法也无法保证返回的是哪个任务的执行结果,反正是其中的某一个
ExecutorService executorService = Executors.newSingleThreadExecutor();

Set> callables = new HashSet>();

callables.add(new Callable() {
public String call() throws Exception {
    return "Task 1";
}
});
callables.add(new Callable() {
public String call() throws Exception {
    return "Task 2";
}
});
callables.add(new Callable() {
    public String call() throws Exception {
    return "Task 3";
}
});

String result = executorService.invokeAny(callables);
System.out.println("result = " + result);
executorService.shutdown();
每次执行都会返回一个结果,并且返回的结果是变化的,可能会返回“Task2”也可是“Task1”或者其它。

invokeAll(...)

invokeAll(...)与 invokeAny(...)类似也是接收一个Callable集合,但是前者执行之后会返回一个Future的List,其中对应着每个Callable任务执行后的Future对象。
ExecutorService executorService = Executors.newSingleThreadExecutor();

Set> callables = new HashSet>();

callables.add(new Callable() {
public String call() throws Exception {
    return "Task 1";
}
});
callables.add(new Callable() {
    public String call() throws Exception {
    return "Task 2";
}
});
callables.add(new Callable() {
    public String call() throws Exception {
      return "Task 3";
   }
});

List> futures = executorService.invokeAll(callables);

for(Future future : futures){
    System.out.println("future.get = " + future.get());
}

executorService.shutdown();

线程池ExecutorService的关闭

如果要关闭ExecutorService中执行的线程,我们可以调用ExecutorService.shutdown()方法。在调用shutdown()方法之后,ExecutorService不会立即关闭,但是它不再接收新的任务,直到当前所有线程执行完成才会关闭,所有在shutdown()执行之前提交的任务都会被执行。

如果我们想立即关闭ExecutorService,我们可以调用ExecutorService.shutdownNow()方法。这个动作将跳过所有正在执行的任务和被提交还没有执行的任务。但是它并不对正在执行的任务做任何保证,有可能它们都会停止,也有可能执行完成。

关注微信公众号:【入门小站】,解锁更多知识点

你可能感兴趣的:(java多线程)