架构师养成记--11.Executor概述
常用方法
Executors.newFiexdPool(int nThreads);固定线程数量的线程池;
Executors.newSingleThreadExecutor();单个线程的线程池;
Executors.newCachedThreadPool();根据实际情况调整线程个数的线程池;每个线程空闲时间60s,过时自动回收;
Executors.newScheduleThreadPool();固定数量线程池,每个线程都可显现定时器。
以上几个线程池都是由ThreadPoolExecutor构造出来的
ThreadPoolExecutor构造方法概述:
ThreadPoolExecutor(
int corePoolSize,//核心线程数,线程池刚初始化的时候实例化线程个数
int maximumPoolSize,//最大线程数
long keepLongTime,//空闲时间,过时回收
TimeUnit unit,//时间单位
BlockingQueue<Runable> worker,//线程暂缓处
ThreadFactory threadFactory,
RejectExecuteHandle handle//拒绝执行的方法
)
Executors.newScheduledThreadPool
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);
scheduler.scheduleWithFixedDelay(command, 1, 3, TimeUnit.SECONDS);
command是Thread对象,1后执行,每3秒执行一次。
自定义线程池的使用
ThreadPoolExecutor pool = new ThreadPoolExecutor(...);
传的参数中,队列是什么类型很重要
有界队列:当前线程数小于corePoolSize,线程立即执行;大于coreSize,并小于maximumPoolSize,线程放入队列;如果队列满了,就执行拒绝方法。
无界队列:除非资源被耗尽,否则不会发生线程被拒绝的情况。以corePoolSize为准,当前线程数大于corePoolSize,线程就会被加入队列。
注:pool.shutdown();不会立即把线程池关闭,而是等线程池中的线程都执行完了,线程池才会关闭。
拒绝策略
AbortPolicy:系统跑出异常,系统继续执行;
discardOldest:丢弃最老的任务,再执行当前新任务;
discardPolicy:丢弃无法执行的任务,不给于任何处理;
callerRunsPolicy:只要线程没有关,会将当前的线程先执行;
自定义策略实现RejectedExecutionHandler接口。
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; public class UseThreadPoolExecutor2 implements Runnable{ private static AtomicInteger count = new AtomicInteger(0); @Override
public void run() {
try {
int temp = count.incrementAndGet();
System.out.println("任务" + temp);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} public static void main(String[] args) throws Exception{
//System.out.println(Runtime.getRuntime().availableProcessors());
BlockingQueue<Runnable> queue =
//new LinkedBlockingQueue<Runnable>();
new ArrayBlockingQueue<Runnable>(10);
ExecutorService executor = new ThreadPoolExecutor(
5, //core
10, //max
120L, //2fenzhong
TimeUnit.SECONDS,
queue); for(int i = 0 ; i < 20; i++){
executor.execute(new UseThreadPoolExecutor2());
}
Thread.sleep(1000);
System.out.println("queue size:" + queue.size()); //输出结果是10,说明在1秒的时候还有10个线程入队等待
Thread.sleep(2000);
} }
重点看一下自定义策略
public class UseThreadPoolExecutor1 {
public static void main(String[] args) {
/**
* 在使用有界队列时,若有新的任务需要执行,如果线程池实际线程数小于corePoolSize,则优先创建线程,
* 若大于corePoolSize,则会将任务加入队列,
* 若队列已满,则在总线程数不大于maximumPoolSize的前提下,创建新的线程,
* 若线程数大于maximumPoolSize,则执行拒绝策略。或其他自定义方式。
*
*/
ThreadPoolExecutor pool = new ThreadPoolExecutor(
1, //coreSize
2, //MaxSize
60, //
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(3) //指定一种队列 (有界队列)
//new LinkedBlockingQueue<Runnable>()
, new MyRejected()
//, new DiscardOldestPolicy()
);
MyTask mt1 = new MyTask(1, "任务1");
MyTask mt2 = new MyTask(2, "任务2");
MyTask mt3 = new MyTask(3, "任务3");
MyTask mt4 = new MyTask(4, "任务4");
MyTask mt5 = new MyTask(5, "任务5");
MyTask mt6 = new MyTask(6, "任务6");
pool.execute(mt1);
pool.execute(mt2);
pool.execute(mt3);
pool.execute(mt4);
pool.execute(mt5);
pool.execute(mt6);
pool.shutdown();
}
}
import java.net.HttpURLConnection;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor; public class MyRejected implements RejectedExecutionHandler{ public MyRejected(){
} @Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("自定义处理..");
System.out.println("当前被拒绝任务为:" + r.toString()); } }
public class MyTask implements Runnable {
private int taskId;
private String taskName;
public MyTask(int taskId, String taskName){
this.taskId = taskId;
this.taskName = taskName;
}
public int getTaskId() {
return taskId;
}
public void setTaskId(int taskId) {
this.taskId = taskId;
}
public String getTaskName() {
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
@Override
public void run() {
try {
System.out.println("run taskId =" + this.taskId);
Thread.sleep(5*1000);
//System.out.println("end taskId =" + this.taskId);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public String toString(){
return Integer.toString(this.taskId);
}
}
架构师养成记--11.Executor概述的更多相关文章
- 架构师养成记--15.Disruptor并发框架
一.概述 disruptor对于处理并发任务很擅长,曾有人测过,一个线程里1s内可以处理六百万个订单,性能相当感人. 这个框架的结构大概是:数据生产端 --> 缓存 --> 消费端 缓存中 ...
- 架构师养成记--12.Concurrent工具类CyclicBarrier和CountDownLatch
java.util.concurrent.CyclicBarrier 一组线程共同等待,直到达到一个公共屏障点. 举个栗子,百米赛跑中,所有运动员都要等其他运动员都准备好后才能一起跑(假如没有发令员) ...
- 架构师养成记--35.redis集群搭建
前记:redis哨兵经验之谈.哨兵做主从切换可能要花费一两秒,这一两秒可能会丢失很多数据.解决方法之一是在java代码中做控制,try catch 到 链接断开的异常就sleep 一两秒钟再conti ...
- 架构师养成记--22.客户端与服务器端保持连接的解决方案,netty的ReadTimeoutHandler
概述 保持客户端与服务器端连接的方案常用的有3种 1.长连接,也就是客户端与服务器端一直保持连接,适用于客户端比较少的情况. 2.定时段连接,比如在某一天的凌晨建立连接,适用于对实时性要求不高的情况. ...
- 架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock
ReentrantLock 有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级. this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决 ...
- 架构师养成记--10.master-worker模式
master-worker模式是一种并行计算模式,分为master进程和worker进程两个部分,master是担任总管角色,worker才是执行具体任务的地方. 总体流程应该是这样的: 具体一点,代 ...
- 架构师养成记--9.future模式讲解
什么是future模式呢?解释这个概念之前我们先来了解一个场景吧,财务系统的结账功能,这个功能可能是每个月用一次,在这一个月中相关的数据量已经积累得非常大,这一个功能需要调用好几个存储过程来完成.假如 ...
- 架构师养成记--8.Queue
一.ConcurrentLinkedQueue 是一个适合在高并发场景下,无锁,无界的,先进先出原则.不允许为null值,add().offer()加入元素,这两个方法没区别:pull().peek( ...
- 架构师养成记--6.单例和多线程、ThreadLocal
一.ThreadLocal 使用wait/notify方式实现的线程安全,性能将受到很大影响.解决方案是用空间换时间,不用锁也能实现线程安全. 来看一个小例子,在线程内的set.get就是thread ...
随机推荐
- 【JS基础】DOM操作
appendChild() //向节点添加最后一个子节点 createElement() //创建元素节点 createTextNode() //创建文本节点,字符串值
- RESTful Api 身份认证安全性设计
REST是一种软件架构风格.RESTful Api 是基于 HTTP 协议的 Api,是无状态传输.它的核心是将所有的 Api 都理解为一个网络资源.将所有的客户端和服务器的状态转移(动作)封装到 H ...
- 【原】tomcat 7 启动报错:java.lang.NoSuchMethodError: javax.servlet.ServletContext.getSessionCookieConfig()Ljavax/servlet/SessionCookieConfig的解决
现象: tomcat 7 启动报错:java.lang.NoSuchMethodError: javax.servlet.ServletContext.getSessionCookieConfig() ...
- 谈一谈前端多容器(多webview平台)处理方案
文中是我个人的一些开发经验,希望对各位有用,也希望各位多多支持讨论,指出文中不足以及提出您的一些建议. 双容器 得益于近几年移动端的发展,前端早已今非昔比,从大型框架来说angularJS.react ...
- JavaScript中数据类型转换总结
JavaScript中数据类型转换总结 在js中,数据类型转换分为显式数据类型转换和隐式数据类型转换. 1, 显式数据类型转换 a:转数字: 1)Number转换: 代码: var a = " ...
- [译]为什么我要离开gulp和grunt转投npm脚本的怀抱
原文链接:https://medium.freecodecamp.com/why-i-left-gulp-and-grunt-for-npm-scripts-3d6853dd22b8#.n7m1855 ...
- ArcGIS 地图性能优化系列一
经常有客户会咨询到如何提高地图的显示性能.为何ArcMap刷新地图那么缓慢.为何地图服务响应要等待10多秒? 诸如这些问题,虽然它们的表象都是相似的,但是往往在分析排查问题的时候,我们发现背后的原因是 ...
- AngularJS 模块& 表单
模块定义了一个应用程序. 模块是应用程序中不同部分的容器. 模块是应用控制器的容器. 控制器通常属于一个模块. 应用("myApp") 带有控制器 ("myCtrl&qu ...
- 简易版自定义BaseServlet
这几天在学Java Web,一直在思考Servlet重用的问题,就用java的反射机制实现自定义的简易版BaseServlet; 该方式有点像struts2 利用映射获取前端的参数.有兴趣的同学可以自 ...
- 利用Sharding-Jdbc实现分表
你们团队使用SpringMVC+Spring+JPA框架,快速开发了一个NB的系统,上线后客户订单跟雪花一样纷沓而来. 慢慢地,你的心情开始变差,因为客户和产品的抱怨越来越频繁,抱怨的最多的一个问题就 ...