ThreadPoolExecutor 的常用用法

原创 2017年11月14日 23:57:38

ThreadPoolExecutor 的常用用法

平常工作中遇到并发场景的解决方案,一般会将大任务拆分成相互独立的小任务,然后将这些小的任务提交给线程池去执行。

线程池的具体实现大致有ExecutorsnewFixedThreadPool() ,newCachedThreadPool()等等方法。但通过看它们的底层实现都是去new ThreadPoolExecutor(),且在工作中采用这种偏底层的实现方式也更多些,对自己写的并发程序能有更好的控制。

下面以简单程序的形式展现new ThreadPoolExecutor()的用法:

package org.zeng.test.concurrent;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by liu shuangzeng on 2017/11/11 21:14.
 */

public class ThreadPoolTest {

    /**
     * corePoolSize: 核心线程数;如果不设置AllowCoreThreadTimeOut=true,则不会被销毁,即使处于闲置状态
     * maximumPoolSize: 最大线程数;= 核心线程数 + 非核心线程数
     * keepAliveTime, unit: 非核心线程的闲置后的生命周期
     * BlockingQueue: 阻塞队列;线程池提交任务时先会创建核心线程,如果核心线程不够了,则会将任务塞到队列中;如果队列也满了,则开始创建非核心线程处理任务;
     * 如果非核心线程也不够用了,则新来的任务会进入 RejectedExecutionHandler 处理。。
     * 关于 BlockingQueue,虽然它是 Queue 的子接口,但是它的主要作用并不是容器,而是作为线程同步的工具,它有一个特征,
     * 当生产者试图向 BlockingQueue 放入(put)元素,如果队列已满,则该线程被阻塞;当消费者试图从 BlockingQueue 取出(take)元素,如果队列已空,则该线程被阻塞。
     * @param size
     * @return
     */
    public static ThreadPoolExecutor getThreadPool(int size) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(size, 10, 30, TimeUnit.DAYS,
                new LinkedBlockingDeque<Runnable>(5), new ThreadFactory() {
            private final AtomicInteger atomicInteger = new AtomicInteger();

            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "test-" + atomicInteger.incrementAndGet());
            }
        }, new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.out.println("队列满啦,而且线程数量达到最大数量啦!");
                try {
                    executor.getQueue().put(r);
                    System.out.println("卡住了嘛?");
                } catch (Exception e) {
                    System.out.println("塞入队列异常啦!");
                }
                System.out.println("塞进队列成功!");
            }
        });
        return threadPoolExecutor;
    }

    public static void main(String args[])  throws Exception{
        ThreadPoolExecutor threadPoolExecutor = getThreadPool(3);
        for (int i = 0; i < 20; i++) {
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    work();
                }
            });
//            Future future = threadPoolExecutor.submit(new Runnable() {
//                @Override
//                public void run() {
//                    work();
//                }
//            });
//            future.get(); //会阻塞当前线程
            System.out.println("当前队列的剩余容量:" + threadPoolExecutor.getQueue().remainingCapacity());
        }
    }

    public static void work() {
        try{
            System.out.println("线程: " + Thread.currentThread().getName() + "进来啦!");
            Thread.sleep(1000l);
        } catch (Exception e) {

        }
    }
}

new ThreadPoolExecutor()的参数比较多,但理解了:线程池提交任务时先会创建核心线程,如果核心线程不够了,则会将任务塞到队列中;如果队列也满了,则开始创建非核心线程处理任务; 如果非核心线程也不够用了,则新来的任务会进入RejectedExecutionHandler处理 这个过程也就不那么难记忆和使用了。

注意的点:
1. 如果不为BlockingQueue指定容量的化,它默认容量是Integer.MAX_VALUE,此时若maximumPoolSize > corePoolSize,那么基本上永远也不会去创建非核心线程,除非你的任务真的塞满了Integer.MAX_VALUE大小的队列.
2. 一种可以通俗理解的优先级: 核心线程 > 队列 > 非核心线程 > RejectedExecutionHandler

ThreadPoolExecutor的例子与应用方式

JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor)使用简介java 2009-11-26 11:26:16 阅读60 评论0 字号:大中小 ...
  • xtwolf008
  • xtwolf008
  • 2012年03月11日 23:36
  • 4157

ThreadPoolExecutor原理及使用

ThreadPoolExecutor原理及使用
  • xiamizy
  • xiamizy
  • 2014年11月04日 11:22
  • 13369

ThreadPoolExecutor中的submit()方法详细讲解

ThreadPoolExecutor中的submit()方法详细讲解在使用线程池的时候,发现除了execute()方法可以执行任务外,还发现有一个方法submit()可以执行任务。submit()有3...
  • qq_33689414
  • qq_33689414
  • 2017年06月09日 11:10
  • 1831

python 8-5 如何使用线程池 线程池是指分配固定个数的线程,concurrentfutues下的ThreadPoolExecutor

8-5 如何使用线程池解决方案: 线程池是指分配固定个数的线程线程池 python3 标准库中concurrentfutues下的ThreadPoolExecutor 对象的submit 和 ...
  • u013679490
  • u013679490
  • 2017年01月28日 17:38
  • 998

Android 线程池框架、Executor、ThreadPoolExecutor详解

一、Java线程池 Java通过Executors提供四种线程池,分别为: newCachedThreadPool 创建一个可缓存线程池,线程池的最大长度无限制,但如果线程池长度超过处理需要,可灵活回...
  • wangbaochu
  • wangbaochu
  • 2016年12月30日 12:26
  • 1321

Java多线程-线程池ThreadPoolExecutor构造方法和规则

为什么用线程池博客地址 http://blog.csdn.net/qq_25806863原文地址 http://blog.csdn.net/qq_25806863/article/details/71...
  • qq_25806863
  • qq_25806863
  • 2017年05月03日 17:15
  • 7909

Java中的线程池——3种常用的ThreadPoolExecutor

在Executor框架下,利用Executors的静态方法可以创建三种类型的常用线程池。他们可分别对应不同的应用场景,下面来看看这三个线程池。 1 FixedThreadPool 这个线程...
  • u010723709
  • u010723709
  • 2015年12月24日 09:25
  • 2349

深入了解ThreadPoolExecutor类的工作原理

原文连接:http://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用   在前面的文章中,我们使用线程的...
  • weishiwei0923
  • weishiwei0923
  • 2015年08月03日 16:13
  • 540

ThreadPoolExecutor原理与使用

ThreadPoolExecutor是java.util.concurrent包提供的基础线程池,使用非常广泛 让我们来看一下线程池的使用和内部实现原理 下面是ThreadPoolExecutor...
  • u010031673
  • u010031673
  • 2016年06月29日 00:41
  • 697

ThreadPoolExecutor基本原理

概述ThreadPoolExecutor是Java中最基本的线程池实现,Executors类的工厂方法newFixedThreadPool()、newCachedThreadPool()、newSin...
  • howard_90
  • howard_90
  • 2015年08月24日 10:56
  • 455
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ThreadPoolExecutor 的常用用法
举报原因:
原因补充:

(最多只允许输入30个字)