架构师养成记--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 ...
随机推荐
- 面向云的.net core开发框架
目录结构 1 为什么搭建面向云的.Net core云开发框架 2 主要设计思路 3 项目解决方案 4 基础设施层 4.1反射工具 4.2多级可换源的配置(上) 42多级可换源的配置(下) 4.3可配置 ...
- About 静态代码块,普通代码块,同步代码块,构造代码块和构造函数的纳闷
构造函数用于给对象进行初始化,是给与之对应的对象进行初始化,它具有针对性,函数中的一种.特点:1:该函数的名称和所在类的名称相同.2:不需要定义返回值类型.3:该函数没有具体的返回值.记住:所有对象创 ...
- Qt——组件位置随窗口变化
当我们用Qt Designer设计界面时,有时会面临这样一个问题:需要在窗口指定位置放置组件,并且当窗口位置大小改变时,该组件相对其父对象的位置是不变的,如下面两幅图所示 ,首先看上面这幅图,注意bu ...
- jQuery 中bind(),live(),delegate(),on() 区别(转)
当我们试图绑定一些事件到DOM元素上的时候,我相信上面这4个方法是最常用的.而它们之间到底有什么不同呢?在什么场合下用什么方法是最有效的呢? 准备知识: 当我们在开始的时候,有些知识是必须具备的: D ...
- XTemplate语法基础
XTemplate 是富逻辑的 KISSY 模板引擎,面向复杂的业务逻辑场景,同时保持高性能和丰富的配置方法,是易学易懂的模板语言. 一个典型的XTemplate模板实例: Hello {{name} ...
- Animation
Animation 效果 用法 1.非常简单,导入两个文件(UIView+SetRect) (UIView+ImageEffects) 源码 github源码:https://github.com/m ...
- luke使用
Luke介绍 Luke是一个方便的索引查看和诊断工具,可以访问Lucene构建的索引文件,显示和修改某些索引内容.能提供: 通过document编号或term浏览索引 查看document内容,可复制 ...
- JAVA编程思想(第四版)学习笔记----11.10 Map
之前学习的是Collection层次的List接口.List层次比较简单,除去与多线程安全相关的CoppyOnWriteArrayList<T>类,这一个类在集中涉及多线程相关知识时候再学 ...
- Oracle死锁
当两个或多个用户相互等待锁定的数据时就会发生死锁,这时这些用户被卡在不能继续处理业务,oracle可以自动检测死锁并解决他们,通过回滚一个死锁中的语句,释放锁定的数据,回滚的话会遇到ora-00060 ...
- asp.net mvc 之旅 —— 第五站 从源码中分析asp.net mvc 中的TempData
在mvc的controller中,我们知道有很多的临时变量存放数据,比如说viewData,viewBag,还有一个比较特殊的tempData,关于前两个或许大家都明白, 基本上是一个东西,就是各自的 ...