并发编程高级篇

多线程框架

Executor框架

在java.util.concurrent包中,是Jdk并发包得核心,其中有一个重要得类:Executors,他扮演着线程工厂得角色,我们通过Executors创建特定的线程池。

newFixedThreadPool()方法,该方法返回一个固定数量得线程池,该方法得线程数始终保持不变,当有一个任务提交得时候,若线程池空闲,即立即执行,若不空闲,就被暂缓在一个任务队列中等待有空闲得线程去执行。

newSingleThreadExecutor()方法,创建一个线程得线程池,若空闲则执行,若不空闲,就被暂缓在一个任务队列中等待有空闲得线程去执行。

newCachedThreadPool()方法,返回一个可根据实际情况调整线程个数的线程池,不限制最大的线程数量,若有任务,则创建线程,若无任务则不创建线程。如果没有任务,空闲线程默认在60s后回收。

newScheduledThreadPool()方法,该方法返回一个SchededExecutorSerice对象,但该线程可以指定线程的数量。

 

做个ScheduledThread的小案列

class Task extends Thread {

@Override

public void run() {

System.out.println(Calendar.getInstance().getTime().getSeconds() + "run");

}

}

 

public class ScheduledJob {

public static void main(String[] args) {

Task task = new Task();

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

ScheduledFuture<?>  schedulerTask = scheduler.scheduleWithFixedDelay(task, 1, 3, TimeUnit.SECONDS);

}

}

scheduleWithFixedDelay()里面的参数,第一个任务进程,第二个延时时间,第三个轮询时间,第四个时间单位。

自定义线程池

上面提到的四种创建线程池的方式 追根接底 就是实现ThreadPoolExecutor这个类

构造方法如下

public ThreadPoolExecutor(int corePoolSize,

int maximunPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler)

初始化线程数 corePoolSize

最大线程数 maximumPoolSize

空闲线程关闭时间 keepAliveTime

时间单位 unit

溢出缓存队列 workQueue

线程工厂(没用) threadFactory

线程拒绝策略 handler

所以我们自定义线程池时,关键在于ThreadPoolExecutor的构造

这个构造方法对于队列时什么类型比较关键

在使用有界队列时:若有新任务需要执行,如果实际线程数小于corePoolSize,则优先创建线程,若大于corePoolSize,则会将任务加入队列,若队列已满,则总线程在不大于maxmumPoolSize的前提下,创建新的线程,否则执行拒绝策略,或其他自定义方式。

在使用无界队列时:LinkedBlockingQueue。与有界队列相比,除非资源耗尽,否则无界的任务队列不存在任务入队失败的情况,当新任务到来的时候,系统的线程数小于corePoolSize时,则新建线程执行任务。当到达corePoolSize后,就不会继续增加,若后续仍有新的任务加入,而又没有空闲的线程资源,则任务会进入队列等待,若任务处理和创建的速度相差很大,无界队列会保持快速的增长,直到系统资源耗尽。

JDK拒绝策略:

AbortPolicy:直接抛出异常阻止系统正常工作。

CallerRunPolicy:只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的线程。

DiscardOldestPolicy:丢弃最老的一个请求,尝试再次提交当前任务。

DiscardPolicy:丢弃无法处理的一个请求,不给予任何处理。

默认是:抛出异常,程序继续执行。

以上列的四种在开发中不常用,适合场景太少,因为对于正常场景来说,每个Task都是重要的。所以我们需要自定义拒绝策略。

如果需要自定义拒绝策略可以实现RejectedExecutionHandler。

public class MyRejected implements RejectedExecutionHandler {

@Override

public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {

//这里获取到被处理的线程,继承Runnable接口,所以如果我们想获得更多的信息,就要就要写详细r.toString(),将线程的详细信息写在里面最好封装程一个json后台直接拼接成一个对象

//处理的时候可以调http请求返回,报告线程未执行,或者做个任务表,将拒绝的任务放在里面,或者写到日志里面

System.out.println("自定义处理..当前被拒绝的任务为:"+r.toString());

}

}

 

关闭线程池

Shutdown() 优雅关机,底层 运用Runtime.addShutdownHook

ShutdownNow()  会报InterruptedException异常

更多有待补充.........................

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值