线程池

线程池的优点

1)避免线程的创建和销毁带来的性能开销。
2)避免大量的线程间因互相抢占系统资源导致的阻塞现象。
3}能够对线程进行简单的管理并提供定时执行、间隔执行等功能。

概念

Java里面线程池的顶级接口是 Executor,不过真正的线程池接口是 ExecutorService, ExecutorService 的默认实现是 ThreadPoolExecutor;普通类 Executors 里面调用的就是 ThreadPoolExecutor。

public interface Executor {
    void execute(Runnable command);
}

public interface ExecutorService extends Executor {
    void shutdown();
    List shutdownNow();
    
    boolean isShutdown();
    boolean isTerminated();
    
     Future submit(Callable task);
     Future submit(Runnable task, T result);
    Future submit(Runnable task);
    ...
}

public class Executors {
    public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, 
                            new SynchronousQueue());
    }
    ...
}

创建一个最简单的线程池:

ExecutorService pool = Executors.newCachedThreadPool();

Executors 提供四种线程池:

  1. newCachedThreadPool 是一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute() 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。注意,可以使用 ThreadPoolExecutor 构造方法创建具有类似属性但细节不同(例如超时参数)的线程池。

  2. newSingleThreadExecutor 创建是一个单线程池,也就是该线程池只有一个线程在工作,所有的任务是串行执行的,如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它,此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

  3. newFixedThreadPool 创建固定大小的线程池,每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小,线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

  4. newScheduledThreadPool 创建一个大小无限的线程池,此线程池支持定时以及周期性执行任务的需求。

通过 ThreadPoolExecutor 的构造函数,撸一撸线程池相关参数的概念:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue workQueue,
                          ThreadFactory threadFactory) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, 
        threadFactory, defaultHandler);
}
  1. corePoolSize:线程池的核心线程数,一般情况下不管有没有任务都会一直在线程池中一直存活,只有在 ThreadPoolExecutor 中的方法 allowCoreThreadTimeOut(boolean value) 设置为 true 时,闲置的核心线程会存在超时机制,如果在指定时间没有新任务来时,核心线程也会被终止,而这个时间间隔由第3个属性 keepAliveTime 指定。

  2. maximumPoolSize:线程池所能容纳的最大线程数,当活动的线程数达到这个值后,后续的新任务将会被阻塞。

  3. keepAliveTime:控制线程闲置时的超时时长,超过则终止该线程。一般情况下用于非核心线程,只有在 ThreadPoolExecutor 中的方法 allowCoreThreadTimeOut(boolean value) 设置为 true时,也作用于核心线程。

  4. unit:用于指定 keepAliveTime 参数的时间单位,TimeUnit 是个 enum 枚举类型,常用的有:TimeUnit.HOURS(小时)、TimeUnit.MINUTES(分钟)、TimeUnit.SECONDS(秒) 和 TimeUnit.MILLISECONDS(毫秒)等。

  5. workQueue:线程池的任务队列,通过线程池的 execute(Runnable command) 方法会将任务 Runnable 存储在队列中。

  6. threadFactory:线程工厂,它是一个接口,用来为线程池创建新线程的。

推荐手动创建线程池而不是直接使用newCachedThreadPool()

ThreadFactory indexThreadFactory = new ThreadFactoryBuilder()
                .setNameFormat("init-index-pool-%d").build();
ExecutorService executorService = new ThreadPoolExecutor(
                4, 4, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue(), indexThreadFactory);
//启动线程
executorService.submit(ThreadImRunnable);

线程池的关闭

ThreadPoolExecutor 提供了两个方法,用于线程池的关闭,分别是 shutdown() 和 shutdownNow()。

shutdown():不会立即的终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务。
shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务。

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