【Java并发专题之十】juc-locks之线程池框架概述

环境
  jdk version:jdk1.8.0_171

一、Executor接口
执行器接口,也是最顶层的抽象核心接口, 分离了任务和任务的执行。

二、ExecutorService接口
在Executor的基础上提供了执行器生命周期管理,任务异步执行等功能。
在Executor的基础上增强了对任务的控制,同时包括对自身生命周期的管理,主要有四类:
(1)关闭执行器,禁止任务的提交;
(2)监视执行器的状态;
(3)提供对异步任务的支持;
(4)提供对批处理任务的支持。

AbstractExecutorService,ExecutorService的抽象实现,为各类执行器类的实现提供基础。
ThreadPoolExecutor,线程池Executor,也是最常用的Executor,可以以线程池的方式管理线程。

三、ScheduledExecutorService接口
在ExecutorService基础上提供了任务的延迟执行/周期执行的功能。ScheduledThreadPoolExecutor,在ThreadPoolExecutor基础上,增加了对周期任务调度的支持。

四、Executors类
生产具体的执行器的静态工厂,提供了五类可供创建的Executor执行器实例。
1、固定线程数的线程池:在初始化时确定其中的线程总数,运行过程中会始终维持线程数量不变。

/**
 * 创建一个具有固定线程数的Executor.
 */
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>());
}

/**
 * 创建一个具有固定线程数的Executor.
 * 在需要时使用提供的 ThreadFactory 创建新线程.
 */
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
    return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(), threadFactory);

}

ThreadFactory,线程工厂,用于创建单个线程,减少手工创建线程的繁琐工作,同时能够复用工厂的特性。

/**
 * 默认的线程工厂.
 */
static class DefaultThreadFactory implements ThreadFactory {
    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    DefaultThreadFactory() {
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
        namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-";
    }

    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
        if (t.isDaemon())
            t.setDaemon(false);
        if (t.getPriority() != Thread.NORM_PRIORITY)
            t.setPriority(Thread.NORM_PRIORITY);
        return t;
    }
}

2、单个线程的线程池

/**
 * 创建一个使用单个 worker 线程的 Executor.
 */
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
                    new LinkedBlockingQueue<Runnable>()));
}

/**
 * 创建一个使用单个 worker 线程的 Executor.
 * 在需要时使用提供的 ThreadFactory 创建新线程.
 */
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
    return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
                    new LinkedBlockingQueue<Runnable>(), threadFactory));
}

3、可缓存的线程池:出于资源利用率的考虑,希望在特定的时候对线程进行回收(比如线程超过指定时间没有被使用)。

/**
 * 创建一个可缓存线程的Execotor.
 * 如果线程池中没有线程可用, 则创建一个新线程并添加到池中;
 * 如果有线程长时间未被使用(默认60s, 可通过threadFactory配置), 则从缓存中移除.
 */
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
            new SynchronousQueue<Runnable>());
}

/**
 * 创建一个可缓存线程的Execotor.
 * 如果线程池中没有线程可用, 则创建一个新线程并添加到池中;
 * 如果有线程长时间未被使用(默认60s, 可通过threadFactory配置), 则从缓存中移除.
 * 在需要时使用提供的 ThreadFactory 创建新线程.
 */
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
            new SynchronousQueue<Runnable>(), threadFactory);
}

4、可延时/周期调度的线程池

/**
 * 创建一个具有固定线程数的 可调度Executor.
 * 它可安排任务在指定延迟后或周期性地执行.
 */
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

/**
 * 创建一个具有固定线程数的 可调度Executor.
 * 它可安排任务在指定延迟后或周期性地执行.
 * 在需要时使用提供的 ThreadFactory 创建新线程.
 */
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory) {
    return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}

5、Fork/Join线程池

ForkJoinPool:Fork/Join线程池,在JDK1.7时引入,时实现Fork/Join框架的核心类。

/**
 * 创建具有指定并行级别的ForkJoin线程池.
 */
public static ExecutorService newWorkStealingPool(int parallelism) {
    return new ForkJoinPool(parallelism, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true);
}

/**
 * 创建并行级别等于CPU核心数的ForkJoin线程池.
 */
public static ExecutorService newWorkStealingPool() {
    return new ForkJoinPool(Runtime.getRuntime().availableProcessors(), ForkJoinPool.defaultForkJoinWorkerThreadFactory,
            null, true);
}

参考:

executors框架总览

原文地址:https://www.cnblogs.com/cac2020/p/12208527.html

时间: 2024-10-07 19:13:39

【Java并发专题之十】juc-locks之线程池框架概述的相关文章

Java并发编程(十二):线程池的使用(转载)

本文转载自:http://www.cnblogs.com/dolphin0520/p/3932921.html 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. 那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务? 在Java中可以通过线程池来达到这样的效果.

《Java并发编程实战》----(八)线程池的使用

1,线程饥饿死锁 在线程池中,如果任务依赖于其他任务,那么可能产生死锁.在单线程的Executor中,如果一个任务将另一个任务提交到同一个Executor,并且等待这个被提交任务的结果,那么通常会引发死锁.第二个任务停留在工作队列中,等待第一个任务完成,而第一个任务又无法完成,因为它在等待第二个任务的完成.在更大的线程池中,如果所有正在执行任务的线程都由于等待其他仍处于工作队列中的任务而阻塞,也会发生统一的问题.这种现象叫做线程饥饿死锁(Thread Starvation Deadlock),只

Java 并发专题 : Executor详细介绍 打造基于Executor的Web服务器

适配器模式,将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 应用场景:系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配.适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况. 代码实现: //Adapter.h #include "stdafx.h" #include <iostream> class Adaptee

Java 并发专题 :闭锁 CountDownLatch 之一家人一起吃个饭

最近一直整并发这块东西,顺便写点Java并发的例子,给大家做个分享,也强化下自己记忆. 每天起早贪黑的上班,父母每天也要上班,话说今天定了个饭店,一家人一起吃个饭,通知大家下班去饭店集合.假设:3个人在不同的地方上班,必须等到3个人到场才能吃饭,用程序如何实现呢? 作为一名资深屌丝程序猿,开始写代码实现: package com.zhy.concurrency.latch; public class Test1 { /** * 模拟爸爸去饭店 */ public static void fath

Java 并发专题 :FutureTask 实现预加载数据 在线看电子书、浏览器浏览网页等

继续并发专题~ FutureTask 有点类似Runnable,都可以通过Thread来启动,不过FutureTask可以返回执行完毕的数据,并且FutureTask的get方法支持阻塞. 由于:FutureTask可以返回执行完毕的数据,并且FutureTask的get方法支持阻塞这两个特性,我们可以用来预先加载一些可能用到资源,然后要用的时候,调用get方法获取(如果资源加载完,直接返回:否则继续等待其加载完成). 下面通过两个例子来介绍下: 1.使用FutureTask来预加载稍后要用的的

玩转Java并发工具,精通JUC,成为并发多面手

玩转Java并发工具,精通JUC,成为并发多面手 深度解密JUC库,提升五位一体的并发综合实力 使用场景+作用+底层原理逐一解读,吃透JUC并发包 掌握丰富的并发工具,解决实际问题,面试.工作轻松搞定 链接:https://pan.baidu.com/s/1ehvQUq9LUmmrZHYH7_DuGw 提取码:jyfs 全网程序学习资料,包含Java后端.前端.人工智能大数据.Python.数据结构和算法.运维.测试.面试相关等课程,所有视频资料均无加密,普通播放器就可播放,加客服微信coder

Java并发学习之二——获取和设置线程信息

本文是学习网络上的文章时的总结,感谢大家无私的分享. Thread类的对象中保存了一些属性信息能够帮助我们辨别每一个线程,知道它的一些信息 ID:每个线程的独特标示: Name:线程的名称: Priority:线程对象的优先级.优先级别在1-10之间,1是最低级,10是最高级. Status:线程状态.在java中,线程只有6种状态:new,runnable,blocked,waiting,time waiting 或terminated. 现在写一个程序,将线程的信息保存到文件中方便查看 pa

Java并发编程学习笔记(一)线程安全性 1

什么是线程安全性: 要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对共享的和可变的状态的访问."共享"意味着变量可以由多个线程同时访问,而"可变"则意味着变量的值在其生命周期内可以发生变化. 一个对象是否需要线程安全的,取决于他是否被多个线程访问.这指的是在程序中访问对象的方式,而不是对象要实现的功能.要使得对象时线程安全的,需要采用同步机制来协同对对象可变状态的访问.如果无法实现协同,那么可能导致数据破坏以及其他不该出现的结果. 如果当多个线程访

高并发第十四弹:线程池的介绍及使用

单线程就不说了因为简单,并且 在实际的生产环境中一般必须来说 线程资源都是由线程池提供线程资源的. 线程池的好处 重用存在的线程,减少对象创建.消亡的开销,性能好 可有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞. 提供定时执行.定期执行.单线程.并发数控制等功能. 在线程池的类图中,我们最常使用的是最下边的Executors,用它来创建线程池使用线程.那么在上边的类图中,包含了一个Executor框架,它是一个根据一组执行策略的调用调度执行和控制异步任务的框架,