精华内容
下载资源
问答
  • @Autowired private ExecutorService executorService;Set> callables = new HashSet>();callables.add(new Callable() {public Map call() throws Exception {Map map = new HashMap();return map;...

    @Autowired private ExecutorService executorService;

    Set> callables = new HashSet>();

    callables.add(new Callable() {

    public Map call() throws Exception {

    Map map = new HashMap();

    return map;

    }

    });

    callables.add(new Callable() {

    public Map call() throws Exception {

    Map map = new HashMap();

    return map;

    }

    });

    callables.add(new Callable() {

    public Map call() throws Exception {

    Map map = new HashMap();

    return map;

    }

    });

    callables.add(new Callable() {

    public Map call() throws Exception {

    Map map = new HashMap();

    return map;

    }

    });

    callables.add(new Callable() {

    public Map call() throws Exception {

    Map map = new HashMap();

    return map;

    }

    });

    List> futures = executorService.invokeAll(callables);// 收集线程返回的值

    for(Future future :  futures) {

    Map map = future.get();// 各个线程返回的map集合

    }

    展开全文
  • JAVA 查看线程池状态

    千次阅读 2020-04-02 13:55:44
    /** * 线程池状态查看 */ public class TestThread { private static ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(10, new BasicThreadFactory.Builder().namingPattern("schedule-pool-...
    
    
    //<!-- 需要依赖 pool 对象池 -->
    //<dependency>
    //<groupId>org.apache.commons</groupId>
    //<artifactId>commons-pool2</artifactId>
    //</dependency>
    
    import org.apache.commons.lang3.concurrent.BasicThreadFactory;
    
    import java.util.TimerTask;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.ScheduledThreadPoolExecutor;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    
    /**
     * 线程池状态查看
     */
    public class TestThread {
        private static ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(10, new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build());
    
        public static void main(String[] args) {
            executor.schedule(newTask("aaa"), 10, TimeUnit.MILLISECONDS);
            executor.schedule(newTask("bbb"), 10, TimeUnit.MILLISECONDS);
            executor.schedule(newTask("ccc"), 10, TimeUnit.MILLISECONDS);
            executor.schedule(newTask("一秒"), 1000, TimeUnit.MILLISECONDS);
            executor.schedule(newTask("5秒"), 5000, TimeUnit.MILLISECONDS);
            executor.schedule(badTask(), 10, TimeUnit.MILLISECONDS);
    
    
            while (getPoolInfo((ThreadPoolExecutor) executor) > 0) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        private static int getPoolInfo(ThreadPoolExecutor tpe) {
            System.out.println();
            int queueSize = tpe.getQueue().size();
            System.out.println("当前排队线程数:" + queueSize);
    
            int activeCount = tpe.getActiveCount();
            System.out.println("当前活动线程数:" + activeCount);
    
            long completedTaskCount = tpe.getCompletedTaskCount();
            System.out.println("执行完成线程数:" + completedTaskCount);
    
            long taskCount = tpe.getTaskCount();
            System.out.println("总线程数:" + taskCount);
    
            //线程池中当前线程的数量,为0时意味着没有任何线程,线程池会终止,此值不会超过MaximumPoolSize
            System.out.println("当前线程的数量:" + tpe.getPoolSize());
    
            //线程池的初始线程数量(当没有任务提交,或提交任务数小于此值值,实际并不会产生那么多线程数)
            System.out.println("线程池的初始线程数量:" + tpe.getCorePoolSize());
    
            //线程池可允许最大的线程数
            System.out.println("线程池可允许最大的线程数" + tpe.getMaximumPoolSize());
            tpe.getLargestPoolSize();
    
            return queueSize;
        }
    
        private static TimerTask newTask(String str) {
            return new TimerTask() {
                @Override
                public void run() {
                    System.err.println("线程:" + Thread.currentThread().getName() + " = " + str);
                }
            };
        }
    
        private static TimerTask badTask() {
            return new TimerTask() {
                @Override
                public void run() {
                    System.err.println("坏的线程:" + Thread.currentThread().getName());
                    //对于异常一定要捕获,否则没有任何提示
                    try {
                        int i = 1 / 0;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };
        }
    }
    

     

    展开全文
  • 后来自己也花时间查看源码,自己去琢磨,多问为什么,结合一些博客的讲解。现在我想把这段时间的成果记录下来,也是为了加深自己的理解吧。下面所有的源码都是java8 源码。1.2 线程池的好处降低性能消耗、提高响应...

    1.对线程池的理解

    1.1 艰辛摸索

    看过许多关于线程池的介绍和讲解,看过方腾飞的 《并发编程的艺术》 也看过很多博客关于线程池的讲解,但是总觉得自己理解的不太好,总觉得哪里缺点。后来自己也花时间查看源码,自己去琢磨,多问为什么,结合一些博客的讲解。现在我想把这段时间的成果记录下来,也是为了加深自己的理解吧。

    下面所有的源码都是java8 源码。

    1.2 线程池的好处

    降低性能消耗、提高响应速度:对于应用需要频繁创建线程,而且线程任务都比较简单,比如一些IO任务,线程的生命周期都很短;而线程的创建需要花费一定的CPU时间,所以当任务到来时如果线程已经准备就绪了,而不是重新创建,则会大大提高系统的响应速度。

    对线程的集中管理监控:将创建的线程规约在线程池里,则可以对线程的数量和运行状态进行管理并进行监控,可对系统的线程资源进行集中管理。

    2.线程池内的一些属性

    2.1 线程池参数

    看下面的这个线程池的构造器,他有许多参数,这些参数都代表什么意思?

    corePoolSize 核心的线程池数量

    maximumPoolSize 线程池内最大的线程数量

    keepAliveTime 线程存活时间

    unit 时间单位 比如 秒 分钟

    workQueue 存储任务的阻塞队列

    threadFactory 自定义线程工厂

    handler 拒绝策略

    3.Executors 提供的几种线程池

    3.1 newFixedThreadPool

    固定线程数的线程池

    3.2 newCachedThreadPool

    缓冲线程池

    3.3 newWorkStealingPool

    jdk 1.8 新加入的。创建一个带并行级别的线程池,并行级别决定了同一时刻最多有多少个线程在执行,如不穿如并行级别参数,将默认为当前系统的CPU个数

    3.4 newScheduledThreadPool

    创建一个定长线程池,支持定时及周期性任务执行。

    4. 源码

    下面介绍下线程池的源码,由于对写作没有天赋,我就尽我最大努力把源码分析的浅显易懂一些。我介绍下线程池的一些状态属性,然后再从提交一个任务开始跟着源码进行描述一下我对源码的理解。

    4.1 线程池状态 和 线程统计

    format,png

    image.png

    ctl

    先看看线程池中最重要的一个属性 ctl,我觉得是Control的简写,ctl控制着整个线程池的运转。ctl是AtomicInteger类型,线程池利用ctl 的高3位作为记录当前线程池的状态。利用低29位记录线程池中线程数,所以线程池中线程的最大容量为 2^29。

    默认值是 1110 0000 0000 0000 0000 0000 0000 0000 = -536 870 912 ;

    COUNT_BITS

    COUNT_BITS = Integer.SIZE - 3;

    COUNT_BITS 的意思是 一个整型数 有29位用于统计线程池内线程数;

    RUNNING 运行状态

    RUNNING 是线程池的初始状态,是一个int 类型的常量,值为 -1 左移 29 位即为 -536 870 912,线程池 的状态

    只有RUNNING 是负数的。

    SHUTDOWN

    RUNNING --shutDowm()--> SHUTDOWN

    RUNNING状态调用shutDowm()函数进入SHUTDOWN状态。是一个int类型的常量 值为0 ;

    此时线程池不接收新任务,但能处理已添加的任务。

    STOP

    (RUNNING or SHUTDOWN) ---shutdownNow()--> STOP

    RUNNING状态或者SHUTSOWN状态调用shutDowmNow()函数进入SROP状态。是一个int类型的常量 值为536 870 912 ;

    不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。

    TIDYING

    是一个int类型的常量 值为1 073 741 824 ;

    SHUTDOWN -> TIDYING:当线程池内线程数为0并且队列内任务数量为0时

    STOP -> TIDYING:当线程池内线程数量为0时

    TERMINATED

    是一个int类型的常量 值为1 610 612 736 ;

    线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。

    CAPACITY (线程的最大容量)

    1 转移 29位 ,就是 0010 0000 0000 0000 0000 0000 0000 0000,

    然后 减1 ,就变成了0001 1111 1111 1111 1111 1111 1111 1111,刚好就是 低29位 为1 ,就是线程内线程的最大容量 。

    4.2 execute 执行任务

    format,png

    线程池添加任务流程图.png

    在未来的某个时刻执行给定的任务,这个任务会被一个新线程或者一个已经存在的线程执行。

    如果任务不能提交执行,那是因为线程池不处于运行状态或者已经到达容量上限。

    那么这个任务就会被RejectedExecutionHandler处理。

    execute()代码逻辑:

    4.3 addWorker

    检查是否可以根据当前线程池状态和绑定条件(核心线程或者最大线程)添加一个新的工作线程。

    如果可以的话那么调整运行的线程数量。

    并且 如果线程成功创建和运行的话,那么firstTask将是新线程的第一个任务被执行。

    如果线程池已经关闭或者正在关闭,函数将返回false.

    如果线程创建失败,可能的原因是因为线程工厂返回null,或者异常(最可能的异常就是在执行Thread,start()时产生OutOfMemoryErro )。

    接着回滚以上操作。

    参数:core:如果为true 增加核心线程,false 增加最大线程。

    4.3 addWorkerFailed

    执行addWorker添加任务失败之后 调用该方法执行回滚操作。

    回滚操作主要做了以下三件事情:

    4.4 runWorker 执行任务

    添加worker 成功之后,worker就开始执行runWorker()了。

    这个方法是比较重要的方法,是线程池的核心。是worker 线程 运行循环,重复地从队列中获取任务并执行它们,同时处理以下一些问题:

    4.5 getTask() 获取任务

    阻塞或者限时的通过getTask() 函数获取任务。不仅仅是获取任务,同时通过是不是返回null控制者worker 线程的退出与否。以下情况会导致函数返回null,导致worker 退出:

    4.6 processWorkerExit 处理worker退出

    对即将死亡worker 进行清理 和 记账(统计worker执行的任务数)

    如果worker突然死亡(执行中有异常) 就需要调整运行的线程数

    将worker 从worker线程集合中移除。(除名)

    可能会终止线程池

    在小于STOP状态前提下,如果由于执行 用户任务异常导致线程退出,创建新线程替代

    在小于STOP状态前提下,不允许核心线程退出,如果运行中的线程小于核心线程,创建新线程替代。

    4.7 tryTerminate 尝试终止池

    1.如果池是shutdown 并且 阻塞队列 为空 并且 工作线程数 为空 转换为终止状态

    2.如果 池是 stop 并且 工作线程为空 转换为 终止状态

    3.满足终止条件,但是工作线程不为 0 ,终止一个空闲线程

    4.8 interruptIdleWorkers

    中断可能等待任务的线程。如果队列任务是空的,有的线程会被一直阻塞,调用该方法会中断那些被一直阻塞的线程:

    展开全文
  • 异步编程工具在Android开发中目前最被推荐的就是Kotlin协程,在引入Kotlin协程机制前,除了响应式扩展(RxJava)兼任异步编程工具外,Java API中线程与线程池就是最重要异步编程手段。而对于Android平台的Kotlin协程...

    异步编程工具在Android开发中目前最被推荐的就是Kotlin协程,在引入Kotlin协程机制前,除了响应式扩展(RxJava)兼任异步编程工具外,Java API中线程与线程池就是最重要异步编程手段。而对于Android平台的Kotlin协程实现来说,依然使用的是线程池来作为任务执行的载体,所以可以将Android平台的Kotlin协程简单的理解是对线程池的一种高度封装。

    Executors.newFixedThreadPool(10).asCoroutineDispatcher()

    Dispatchers.IO.asExecutor()

    复制代码

    因此我们先了解Java线程池是如何运行的,再深入理解Kotlin协程是如何实现的。

    从Thread到Executor

    线程的创建通过Thread类,为了复用线程而进行池化就有了线程池。线程池带来了两点明显优势:

    降低重复创建线程的开销

    将任务与线程管理解耦

    Executor接口就是第二点的体现。其execute方法用于执行任务,不必关系这个任务执行的载体究竟是什么,到底有没有创建线程。ThreadPoolExecutor实现类就是这个任务执行器的线程池实现。

    ThreadPoolExecutor的任务添加与线程复用

    public void execute(Runnable command){

    if (command == null)

    throw new NullPointerException();

    int c = ctl.get();

    if (workerCountOf(c) < corePoolSize) {

    if (addWorker(command, true))

    return;

    c = ctl.get();

    }//1

    if (isRunning(c) && workQueue.offer(command)) {

    int recheck = ctl.get();

    if (! isRunning(recheck) && remove(command))

    reject(command);

    else if (workerCountOf(recheck) == 0)

    addWorker(null, false);

    }//2

    else if (!addWorker(command, false))

    reject(command);//3

    }

    复制代码

    查看execute方法可以清楚了解其运行方式:

    当线程数小于corePoolSize时,创建线程并执行任务;

    若任务未通过步骤1添加,则入队workQueue;(主要逻辑在if的条件判断中,而if内的逻辑处理的是在一些异常下,对入队的回滚或补充创建线程)

    若任务未入队,则仍创建线程(上限为maximumPoolSize)并执行任务,失败则执行拒绝策略。

    boolean addWorker(Runnable firstTask, boolean core)就是创建线程的方法,方法中第二个参数代表以corePoolSize还是maximumPoolSize为界,方法内其余创建线程的细节逻辑不深究。但要关注一下线程的封装类Worker,addWorker方法内调用了Worker内被封装线程的start方法,执行Worker的run方法。我们将run方法内的runWorker简化如下:

    void runWorker(Worker w){

    Runnable task = w.firstTask;

    w.firstTask = null;

    while (task != null || (task = getTask()) != null) {

    task.run();

    }

    }

    复制代码

    可以发现,初始任务执行完后,不断通过getTask方法获取任务执行,以此来实现线程的复用,而不是只执行完一个任务就销毁了线程。

    另外查看简化后的getTask方法如下:

    private Runnable getTask(){

    boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

    try {

    Runnable r = timed ?

    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :

    workQueue.take();

    if (r != null)

    return r;

    } catch (InterruptedException retry) { }

    }

    复制代码

    任务是从阻塞队列workQueue中取出的,并且根据配置allowCoreThreadTimeOut与线程个数是否大于corePoolSize,来决定使用BlockingQueue的带超时时间的取任务方法poll,还是阻塞取任务方法take,以实现任务列表为空时适时销毁线程还是阻塞线程。

    回过头来看ThreadPoolExecutor的构造方法:

    public ThreadPoolExecutor(int corePoolSize,

    int maximumPoolSize,

    long keepAliveTime,

    TimeUnit unit,

    BlockingQueue workQueue,

    ThreadFactory threadFactory,

    RejectedExecutionHandler handler)复制代码

    我们可以清楚的明白每个参数的含义,以及它是如何影响线程池中线程的复用了。

    展开全文
  • [1].[代码] TestThreadPool.javapackage ...import java.io.Serializable;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concur...
  • Java线程池需要不断的学习,在学习的时候我们就要注意不少的问题。下面我们就来看看具体的语言运作环境如何才能满足Java线程池相关程序的运行。希望大家有所收获。无论是接收Runnable型参数,还是接收Callable型参数...
  • java_线程池

    2018-09-02 14:29:38
    线程池 线程池的原理 ...Executors的四个常用方法 ... 就是一些线程的集合,线程的状态不是死亡状态,当线程池接收到外面的任务时,线程池查看是否有空闲线程,若有,就会将任务分配给它,任务处于等待队列中 ...
  • 一、等待线程池所有线程完成:有时候我们需要等待java thread pool中所有任务完成后再做某些操作,如想要等待所有任务完成,仅需调用threadPool.awaitTermination()方法即可,请查看如下代码:ExecutorService ...
  • 每个Elasticsearch节点内部都维护着多个线程池,如index、search、get、bulk等,用户可以修改线程池的类型和大小,线程池默认大小跟CPU逻辑一致一、查看当前线程组状态curl -XGET '..."queue" :...
  • java提供的原生线程池技术处理原理很清晰,故只要使用自己的原生线程池技术一般都能满足项目的需求。java提供了很好的线程池实现,比我们自己的实现要更加健壮以及高效,同时功能也更加强大,不建议自己编写。另外有...
  • Java线程池的创建和使用 首先,查看当前cpu核的数量的代码 System.out.println(Runtime.getRuntime().availableProcessors()); 创建线程池首先想到的是使用工具类Executors中的三中方式 第一种 //创建一个单例的...
  • 随着科技的进步,现在的电脑及服务器的处理器数量都比较多,以后可能会越来越多,比如我的工作电脑的处理器有8个,怎么查看呢?计算机右键--属性--设备管理器,打开属性窗口,然后点击“设备管理器”,在“处理器”...
  • 简介线程池Java并发编程中经常使用到的技术,那么自己如何动手写一个线程池呢?本文彤哥将手把手带你写一个可用的线程池。属性分析线程池,顾名思义它首先是一个“池”,这个池里面放的是线程,线程是用来执行任务...
  • 随着科技的进步,现在的电脑及服务器的处理器数量都比较多,以后可能会越来越多,比如我的工作电脑的处理器有8个,怎么查看呢?计算机右键--属性--设备管理器,打开属性窗口,然后点击“设备管理器”,在“处理器”...
  • Java的线程执行中,不管是直接继承Thread的方式,还是实现Runnable接口的方式,都不会获取到线程执行的返回结果。这样如果线程在执行过程中出现了错误,那么主线程也不会感知到。即使打印了日志,也不能立即抛出...
  • 欢迎关注我的公众号“彤哥读源码”,查看更多源码系列文章, 与彤哥一起畅游源码的海洋。(手机横屏看源码更方便)注:java源码分析部分如无特殊说明均基于 java8 版本。注:本文基于ScheduledThreadPoolExecutor定时...
  • (1):线程池存在哪些状态,这些状态之间是如何进行切换的呢?(2):线程池的种类有哪些?(3):创建线程池需要哪些参数,这些参数的具体含义是...查看ThreadPoolExecutor源码便知晓://runState is stored in the high...
  • java并发线程池的使用

    2019-10-07 18:11:00
    原文地址,欢迎查看原博文:https://www.cnblogs.com/dolphin0520/p/3932921.html 转载于:https://www.cnblogs.com/wangxiaochao/p/9322986.html
  • 打开今日头条,查看更多精彩图片本文属于对Java线程池的综合思考,如果您对Java线程池还不太了解,可以先收藏。本文讲解如下几个内容:当核心线程满时,先创建临时线程还是先加入队列?临时线程工作时间和方式?核心...
  • java设置线程池中线程的名字

    万次阅读 2018-03-23 15:06:16
    项目中使用ThreadPoolExecutor进行...如果一个系统中用到了多个线程池,就无法区分哪个线程造成的系统问题。所以每次都需要点 Thread Dumps 去查看线程执行的具体的代码与堆栈信息,推测是哪个地方出的问题。 于是
  • Executor接口如果查看jdk文档,会发现java线程池都源自于这个超级接口Executor,但是这个接口本身比较简单:public interface Executor {/**在未来某个时间执行给定的命令。该命令可能在新的线程、已入池的线程或者...
  • 前面几篇文章我们一直在讲述java线程池的相关知识点,我相信现在大家对java多线程一定有了一些了解,jdk中的核心实现类为java.util.concurrent.ThreadPoolExecutor,前面大家了解到它的原理(可查看:...
  • 关于这些参数最好的学习...我们找到ThreadPoolExecutor 类,查看API 说明如下: 文档是不是解释的很清楚,针对这个参数简单理解就是如果线程超过了我们的核心线程数,那个对于闲置状态的线程最大的存活时间。 ...
  • java线程池

    2016-11-16 11:07:26
    Java提供的原生线程池技术处理原理很清晰,故只要使用自己的原生线程池技术一般都能满足项目的需求。java提供了很好的线程池实现,比我们自己的实现要更加健壮以及高效,同时功能也更加强大,不建议自己编写。另外有...
  • Java线程池

    2019-07-23 17:57:00
    线程池的核心类是ThreadPoolExecutor,查看其构造函数,参数最多的构造函数包含这几个部分 int corePoolSize:核心池大小 int maximumPoolSize:最大线程池大小 long keepAliveTime:线程空闲时任保留等待新任务提交...
  •  简洁之美-java5线程池源码赏析(上) ...一时兴起,查看java5自带的线程池的部分源码,深感震撼,恐忘却,故为此文以记之。网路上对java5的线程池讨论不少,但多数未能阐述其如何复用线程,本...
  • 查看Java线程池实现的源码时,对于线程池内部worker生命周期有一个不解的地方:当worker所持有的task,或者线程队列中的task都被执行完以后,为什么worker要被移除线程池的worker集合。追踪源码的过程大致是:查看...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 549
精华内容 219
关键字:

java查看线程池

java 订阅