线程池系列三:ThreadPoolExecutor讲解
三、一个用队列处理线程池例子
- package demo;
- import java.util.Queue;
- import java.util.concurrent.ArrayBlockingQueue;
- import java.util.concurrent.ThreadPoolExecutor;
- import java.util.concurrent.TimeUnit;
- public class ThreadPoolExecutorTest
- {
- private static int queueDeep = 4;
- public void createThreadPool()
- {
- /*
- * 创建线程池,最小线程数为2,最大线程数为4,线程池维护线程的空闲时间为3秒,
- 缓冲队列为4,线程执行时间是3秒。
- */
- ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueDeep),
- new ThreadPoolExecutor.DiscardOldestPolicy()); //这里采取的是抛弃旧的任务
- // 向线程池中添加 10 个任务
- for (int i = 0; i < 10; i++)
- {
- try
- {
- Thread.sleep(1);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- while (getQueueSize(tpe.getQueue()) >= queueDeep)
- {
- System.out.println("队列已满,等3秒再添加任务");
- try
- {
- Thread.sleep(3000);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- }
- TaskThreadPool ttp = new TaskThreadPool(i);
- System.out.println("put i:" + i);
- tpe.execute(ttp);
- }
- tpe.shutdown();
- }
- private synchronized int getQueueSize(Queue queue)
- {
- return queue.size();
- }
- public static void main(String[] args)
- {
- ThreadPoolExecutorTest test = new ThreadPoolExecutorTest();
- test.createThreadPool();
- }
- class TaskThreadPool implements Runnable
- {
- private int index;
- public TaskThreadPool(int index)
- {
- this.index = index;
- }
- public void run()
- {
- System.out.println(Thread.currentThread() + " index:" + index);
- try
- {
- Thread.sleep(3000);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- }
- }
- }
说明:
这里执行的结果为:
put i:0 0加入进去池子
Thread[pool-1-thread-1,5,main] index:0 0开始执行
put i:1 1加入进去池子
Thread[pool-1-thread-2,5,main] index:1 1开始执行
put i:2 2加入缓冲
put i:3 3加入缓冲
put i:4 4加入缓冲
put i:5 5加入缓冲
队列已满,等3秒再添加任务
(上述代码首先一次性执行,会在这里停一会,因为添加线程不需要时间)
Thread[pool-1-thread-1,5,main] index:2 2开始执行
Thread[pool-1-thread-2,5,main] index:3 3开始执行
put i:6 6加入缓冲
put i:7 7加入缓冲
队列已满,等3秒再添加任务
(会停一会,因为任务执行要3秒时间,2,3,4,5会先执行2,3 ,因为2,3先进入缓冲队列)
Thread[pool-1-thread-1,5,main] index:4
Thread[pool-1-thread-2,5,main] index:5
put i:8
put i:9
(停一会,任务执行要3秒,)
Thread[pool-1-thread-1,5,main] index:6
Thread[pool-1-thread-2,5,main] index:7
(要停一会,任务执行要3秒)
Thread[pool-1-thread-1,5,main] index:8
Thread[pool-1-thread-2,5,main] index:9
(执行完毕)
ps:这里是当队列已满时线程就一直等待了,不会再新创建线程,所以一直就只有1和2两个线程来执行。
如果把
- while (getQueueSize(tpe.getQueue()) >= queueDeep){}
这一段去掉,那么执行结果为:
put i:0
Thread[pool-1-thread-1,5,main] index:0
put i:1
Thread[pool-1-thread-2,5,main] index:1
put i:2
put i:3
put i:4
put i:5
put i:6
Thread[pool-1-thread-3,5,main] index:6
put i:7
Thread[pool-1-thread-4,5,main] index:7
put i:8
put i:9
Thread[pool-1-thread-1,5,main] index:4
Thread[pool-1-thread-2,5,main] index:5
Thread[pool-1-thread-3,5,main] index:8
Thread[pool-1-thread-4,5,main] index:9
ps:这个执行顺序是0,1两个任务先进来,分别由线程1,2来执行,然后2,-5进来,队列满,6任务进来,因为队列已满,且1,2线程还未执行完,没有可用的线程,所以创建新的线程来运行6。7任务同理。然后8任务进来,队列已满,且1,2,3,4线程未执行完,线程数又等于了最多4个线程的限制,这时看线程池的执行策略为DiscardOldestPolicy,就是抛弃旧的任务,故开始进队列的2任务被抛弃,3任务同理,8,9任务进入队列,然后这时1-4线程已经执行完自己的任务,开始执行队列中的4,5,8,9
如果更改执行策略,那么相应的结果也会不一样,如果不希望有任务被抛弃,那么可以采用CallerRunsPolicy()策略。
线程池系列三:ThreadPoolExecutor讲解的更多相关文章
- 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分
这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int ...
- 《java.util.concurrent 包源码阅读》11 线程池系列之ThreadPoolExecutor 第一部分
先来看ThreadPoolExecutor的execute方法,这个方法能体现出一个Task被加入到线程池之后都发生了什么: public void execute(Runnable command) ...
- 《java.util.concurrent 包源码阅读》12 线程池系列之ThreadPoolExecutor 第二部分
接着说worker线程是如何工作的.ThreadPoolExecutor有一个成员类叫Worker,所起到的作用就是线程池worker线程的作用. private final class Worker ...
- java线程池系列(1)-ThreadPoolExecutor实现原理
前言 做java开发的,一般都避免不了要面对java线程池技术,像tomcat之类的容器天然就支持多线程. 即使是做偏后端技术,如处理一些消息,执行一些计算任务,也经常需要用到线程池技术. 鉴于线程池 ...
- 线程池系列二:ThreadPoolExecutor讲解
一.简介 1)线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, i ...
- Java多线程系列--“JUC线程池”04之 线程池原理(三)
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基 ...
- 线程池系列一:线程池作用及Executors方法讲解
线程池的作用: 线程池作用就是限制系统中执行线程的数量. 根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果:少了浪费了系统资源,多了造成系统拥挤效率不高.用线程池控制线程数量 ...
- Java多线程系列——线程池原理之 ThreadPoolExecutor
ThreadPoolExecutor 简介 ThreadPoolExecutor 是线程池类. 通俗的讲,它是一个存放一定数量线程的线程集合.线程池允许多个线程同时运行,同时运行的线程数量就是这个线程 ...
- C# 多线程学习系列三之CLR线程池系列之ThreadPool
一.CLR线程池 1.进程和CLR的关系一个进程可以只包含一个CLR,也可以包含多个CLR2.CLR和AppDomain的关系一个CLR可以包含多个AppDomain3.CLR和线程池的关系一个CLR ...
随机推荐
- vue父子组件通信传值
父组件 -> 子组件 通过props来进行通信 父组件代码: <Children :dataName = "dataContent" /> //dataName: ...
- 通过force index了解的MySQL查询的性能优化
查询是数据库技术中最常用的操作.查询操作的过程比较简单,首先从客户端发出查询的SQL语句,数据库服务端在接收到由客户端发来的SQL语句后, 执行这条SQL语句,然后将查询到的结果返回给客户端.虽然过程 ...
- 三 概要模式 3) MR计数器计数 。无 reduce 计数
计数器模式讲解: 先讲一下,就是说只用 Map 阶段 不需要 Reduce . 也就是说去掉了中间输出,而是Map 直接输出结果.大大提高了 MR 的效率且节省了 MR 中间输出读入 ...
- [Typescript] Promise based delay function using async / await
Learn how to write a promise based delay function and then use it in async await to see how much it ...
- 对象逆序列化报错:java.lang.ClassNotFoundException
简单的想从保存的对象中又一次解析出对象.用了逆序列化,但是报错: java.lang.ClassNotFoundException: xxxxxxxxxxxx at java.net.URLClass ...
- mysql-高级语言语法
一.注释 从#字符到行尾 从'-- '序列到行尾.两个破折号之后至少要有一个空格符或制表符. 二.设置变量 用户变量的形式为@var_name,其中变量名varname可以有当前字符集的文字数字字符. ...
- netty学习(二)--传统的bio编程
网络编程的基本模型是Client/Server模型.也就是两个进程之间进行相互通信,当中服务端提供位置信息( 绑定ip地址和监听port),client通过连接操作向服务端监听的地址发送连接请求,通过 ...
- android JNI 一维数组、二维数组的访问与使用
在JNI中访问JAVA类中的整型.浮点型.字符型的数据比较简单,举一个简单的例子,如下: //得到类名 jclass cls = (*env)->GetObjectClass(env, obj) ...
- Mysql-in查询问题
Mysql-in查询问题 标签(空格分隔): mysql 问题:mysql用in语法查询出来的数据少了好多! 我的实际情况: 数据表: content字段记录着一些选项的id,多个选项用逗号隔开,比如 ...
- Error creating bean with name 'testController': Injection of resource dependencies failed;
启动ssm项目报错: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 't ...