Java并发41:Executor系列--Executors(上)-Runnable转Callable、ThreadFactory和不可配置的线程池

本章主要学习Executors接口。

1.Executors接口概述

@since 1.5

这个类定义了供Executor、ExecutorService、ScheduledExecutorService、ThreadFactory和Callable这些接口和类使用的工厂方法和工具方法。

Executors来自java.util.concurrent,是Executor并发框架的主要工具类。

Executors提供了以下几类方法:

  • 第1类静态方法:将Runnable转换成Callable。
  • 第2类静态方法:线程工厂(ThreadFactory)类。
  • 第3类静态方法:实例化几类不可配置的线程池(ExecutorService和ScheduleExecutorService)。
  • 第4类静态方法:实例化几类预先配置的常用线程池(ExecutorService)。
  • 第5类静态方法:实例化几类预先配置的常用可调度线程池(ScheduleExecutorService)。

本章主要对第1、2、3类静态方法进行说说明。

2.第1类静态方法:将Runnable转换成Callable

通过前面的学习,我们知道Runnable并不能返回运行结果,在某些应用场景下,这种缺陷是很不不方便的。

而Callable作为一种新的线程实现方式,能够返回值。

Executors工具类提供了一系列方法用于将Runnable转化成Callable,下面列出两种:

  • Executors.callable(runnable):将Runnable对象转化成Callable<Object>对象,与之结合的Future对象返回null
  • Executors.callable(runnable, result):将Runnable对象转化成Callable<V>对象,与之结合的Future对象返回result

下面,分别对上述两个方法进行实例编码:

//定义运行结果
final Integer[] result = {null};
//定义一个Runnable接口
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        result[0] = 111111;
    }
};
//定义一个线程池
ExecutorService executorService = Executors.newCachedThreadPool();

//Executors.callable(runnable)=转换成Callable<Object>,Future返回null
Callable<Object> callable = Executors.callable(runnable);
//提交转换成之后的Callable接口
Future future = executorService.submit(callable);
//输出运行结果,肯定是null
System.out.println("Executors.callable(runnable) 的future = " + future.get());

//Executors.callable(runnable, result)=转换成Callable<V>,future有值
Callable<Integer> callable1 = Executors.callable(runnable, result[0]);
//提交转换成之后的Callable接口
Future future1 = executorService.submit(callable1);
//输出运行结果
System.out.println("Executors.callable(runnable, result) 的future = " + future1.get());

运行结果:

Executors.callable(runnable) 的future = null
Executors.callable(runnable, result) 的future = 111111

3.第2类静态方法:线程工厂(ThreadFactory)类

线程工厂(ThreadFactory)类提供了线程创建的工厂方法。

通过线程工厂创建的线程位于同一线程组(ThreadGroup),并且拥有相同的优先级(priority)。

创建线程工厂(ThreadFactory)类的方法如下:

  • Executors.defaultThreadFactory()

下面对这个方法进行实例编码练习:

//创建线程工厂
ThreadFactory threadFactory = Executors.defaultThreadFactory();
//创建多个线程
for (int i = 0; i < 5; i++) {
    Thread thread = threadFactory.newThread(() -> {
        System.out.println(Thread.currentThread() + " : " + 22222);
    });
    //执行此线程
    thread.start();
}

运行结果:

Thread[pool-2-thread-1,5,main] : 22222
Thread[pool-2-thread-2,5,main] : 22222
Thread[pool-2-thread-3,5,main] : 22222
Thread[pool-2-thread-5,5,main] : 22222
Thread[pool-2-thread-4,5,main] : 22222

可以看到,这些线程都属于同一线程组main,且优先级都是默认优先级5。

4.第3类静态方法:不可配置的线程池

Executors类提供了以下两类静态方法,用于创建不可配置的线程池:

  • Executors.unconfigurableExecutorService(executorService):不可配置的线程池
  • Executors.unconfigurableScheduledExecutorService(scheduledExecutorService):不可配置的调度线程池

不可配置的线程池通过代理线程池对象DelegatedExecutorService来禁止方法的强制转换。

这种方式提供了一种安全地“冻结”配置并且不允许调整给定具体实现的方法。

我本身并没有对这两个方法进行实际编码,只是对齐进行基本了解,其使用思路大概如下:

//定义一个线程池服务ExecutorService
ExecutorService executorService1 = null;
//将上述的线程池服务ExecutorService 转换成 不可配置的线程池服务
ExecutorService unconfigurableExecutorService = Executors.unconfigurableExecutorService(executorService1);
//...业务操作
//关闭服务
unconfigurableExecutorService.shutdownNow();

//定义一个可调度的线程池服务ScheduledExecutorService
ScheduledExecutorService scheduledExecutorService = null;
//将上述的线程池服务ScheduledExecutorService 转换成 不可配置的可调度的线程池服务
ScheduledExecutorService unconfigurableScheduledExecutorService = Executors.unconfigurableScheduledExecutorService(scheduledExecutorService);
//...业务操作
//关闭服务
unconfigurableScheduledExecutorService.shutdown();

 

posted @ 2021-09-26 17:44  姚春辉  阅读(248)  评论(0编辑  收藏  举报