做网站有现成的程序,wordpress 汉化模版,乐从网站建设,安溪县建设局网站目录 一 线程池执行原理
二 线程池改造(一)
三 线程池改造(二) 一 线程池执行原理 首先我们先了解一下线程池里面几个参数#xff1a; 第一个是核心线程数#xff0c;第二个是线程池最大线程数。#xff08;线程池里面的线程分为核心线程和非核心线程#xff0c;既然核心…目录 一 线程池执行原理
二 线程池改造(一)
三 线程池改造(二) 一 线程池执行原理 首先我们先了解一下线程池里面几个参数 第一个是核心线程数第二个是线程池最大线程数。线程池里面的线程分为核心线程和非核心线程既然核心线程有3个那么说明还可以创建最多2个非核心线程
第三个是最大空闲时间第四个是时间单位为秒
第五个是阻塞队列这个很重要第六个是线程工厂默认的
最后一个是拒绝策略。
知道了每一个参数后我们现在就来解释线程池的工作原理 首先当任务进入线程池后这里假设线程池是正常运行状态所以这个就不再做判断线程池会先判断任务数量是否大于核心线程池的数量如果不大于那么就直接创建核心线程来执行任务但是如果任务数量大于核心线程池数量比如你只有三个核心线程池但是你有四个任务那么前三个任务会创建核心线程池去执行而多出来的那个任务会放到阻塞队列里面等核心线程空闲了再去执行阻塞队列里面的任务。
但是如果现在来了五个任务那么前三个交给核心线程池第四个放在阻塞队列里面等待而我们设置的阻塞队列只有一个剩下的那个任务就会创建一个非核心线程去执行这个任务。
如果现在来了七个任务前三个交给核心线程第四个放在阻塞队列第五和第六个会创建非核心线程执行那么第七个呢现在非核心线程也已经满了。那么这个时候就会有参数里面的拒绝策略去拒绝这个任务抛异常处理等等。。。
二 线程池改造(一)
以上就是整个线程池执行原理然后我们发现这里就会有个问题。就是当阻塞队列没满的时候任务会等待核心线程执行完才会被执行那如果核心线程执行的任务非常耗时那不是阻塞队列里面的任务就会一直等。
所以我们现在第一个改造就是如果核心线程池占用完了新的任务不是直接去阻塞队列等待而是直接创建非核心线程去执行任务。
怎么改呢
我们先看看ThreadPoolExecutor类里面的execute方法的代码 public void execute(Runnable command) {if (command null)throw new NullPointerException();int c ctl.get();if (workerCountOf(c) corePoolSize) {if (addWorker(command, true))return;c ctl.get();}if (isRunning(c) workQueue.offer(command)) {int recheck ctl.get();if (! isRunning(recheck) remove(command))reject(command);else if (workerCountOf(recheck) 0)addWorker(null, false);}else if (!addWorker(command, false))reject(command);} 从上面的源码可以看见在第三步的时候它的判断如果为true就会把任务放进阻塞队列然后第四步才是创建非核心线程执行任务。
我们现在是想要先创建非核心线程直接执行任务而不是先让任务进入阻塞队列那么我们可以在第三步的判断条件中然后的条件为false那么它就不会进入阻塞队列而是直接跳到下一步创建非核心线程去执行任务。
那么我们只能重写workQueue.offer()方法了。
我们继承阻塞队列这个类然后重写里面的offer方法直接让他返回false
package com.feisi.threadPool;import java.sql.Array;
import java.util.Collection;
import java.util.concurrent.ArrayBlockingQueue;public class TaskQueueR extends Runnable extends ArrayBlockingQueueRunnable {public TaskQueue(int capacity) {super(capacity);}public TaskQueue(int capacity, boolean fair) {super(capacity, fair);}public TaskQueue(int capacity, boolean fair, Collection? extends Runnable c) {super(capacity, fair, c);}Overridepublic boolean offer(Runnable runnable) {
// 重写方法直接返回falsereturn false ; }
}然后我们把线程池的阻塞队列换成我们自己的 看运行结果 原先四个任务前面三个有三个核心线程执行后面一个在阻塞队列等待直到核心线程执行完再去执行它但是现在不一样了任务4直接由非核心线程4去执行了。
三 线程池改造(二)
上面这个问题是解决了我们加快了任务的执行速度无需去等待核心线程执行完毕就可以直接创建非核心线程去执行任务。
但是现在有一个问题就是你直接返回false相当于来一个任务只要没超出最大线程数限制你就直接给他创建一个非核心线程去执行这样线程数多了容易影响性能比如你来了四个任务前三个由核心线程去执行而第四个你就直接创建非核心线程了那如果前面的核心线程已经执行完了呢那是不是可以不需要创建非核心线程了直接由空闲的核心线程去执行就行了这样就可以大大减少线程的创建了。
所以我们应该再做一个判断如果任务总数小于核心线程数那么就由核心线程执行如果大于核心线程数那么就创建新的非核心线程去执行。
package com.feisi.threadPool;import java.sql.Array;
import java.util.Collection;
import java.util.concurrent.ArrayBlockingQueue;public class MyTaskQueueR extends Runnable extends ArrayBlockingQueueRunnable {private EagerThreadPoolExecutor threadPoolExecutor;public MyTaskQueue(int capacity) {super(capacity);}public MyTaskQueue(int capacity, boolean fair) {super(capacity, fair);}public MyTaskQueue(int capacity, boolean fair, Collection? extends Runnable c) {super(capacity, fair, c);}public void setThreadPoolExecutor(EagerThreadPoolExecutor threadPoolExecutor) {this.threadPoolExecutor threadPoolExecutor;}Overridepublic boolean offer(Runnable runnable) {//1.获取当前线程池的线程数量int currentPoolSize threadPoolExecutor.getPoolSize();//如果当前任务数量小于核心线程数, 让核心线程数来执行// 有核心线程在空闲if(threadPoolExecutor.getSubmittedTaskCount() threadPoolExecutor.getCorePoolSize()){
// System.out.println(111);//让核心线程数来执行return super.offer(runnable);}//如果当前线程池线程数量 最大线程池而且说明核心线程没有空闲那么就创建非核心线程执行。if(currentPoolSize threadPoolExecutor.getMaximumPoolSize() ){return false;}//把任务存储到队列中return super.offer(runnable);}
}还需要重写ThreadPollExector类的executor方法来记录当前线程中需要处理的任务数
package com.feisi.threadPool;import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;/*** 快速消费线程池*/
public class EagerThreadPoolExecutor extends ThreadPoolExecutor {public EagerThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueRunnable workQueue) {super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);}public EagerThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueRunnable workQueue, ThreadFactory threadFactory) {super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);}public EagerThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueRunnable workQueue, RejectedExecutionHandler handler) {super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);}public EagerThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueRunnable workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);}private AtomicInteger submittedTaskCount new AtomicInteger(0);//提供公开获取submittedTaskCount值public int getSubmittedTaskCount(){return submittedTaskCount.get();}Overridepublic void execute(Runnable command) {
// System.out.println(进来了..);//任务数 1submittedTaskCount.incrementAndGet();try{Thread.sleep(500);super.execute(command);}catch (Exception e){ //拒绝//任务数-1submittedTaskCount.decrementAndGet();}}//表示任务执行完成的回调方法Overrideprotected void afterExecute(Runnable r, Throwable t) {super.afterExecute(r, t);//任务数-1submittedTaskCount.decrementAndGet();}
}运行结果 可以看见后面的线程也是由核心线程执行的而没有去创建非核心线程因为核心线程是空闲的就不需要再去创建非核心线程了。