ExecutorService executorServer = xxxxxx.getThreadPool();
Future future = executorServer.submit(new xxxxxxx(Param, funcId));
Object obj = future.get(100, TimeUnit.MILLISECONDS); //总超时时间设置
其中,future.get是从开始进行get方法时进行计算的时间,非future生成开始计算的,即什么时候get什么时候开始计时。
线程池从生成线程,如果核心线程不为0,则有任务时一直生成核心线程,直至到核心线程,之后开始方队列中,最后任务多就开始开辟新线程到最大线程数。
执行任务时,首先线程池开辟线程,之后 线程start( execute方法->addWorker-->t.start())后开始执行call方法。但从.start 到 执行call方法,需要CPU进行线程的上下文切换。 可以根据重写的
ThreadPoolExecutor方法来跟踪。
在高并发下,如果线程池不加 executorServer.prestartAllCoreThreads();
则在线程为1500的并发下,即新创建线程start状态为NEW,真正运行时为RUNNABLE(start后),到call真正的调用会耗时,因CPU切换。
如不加,则会有12-160多ms的消耗,
如果加上prestartAllCoreThreads()则性能会好很多,最大从start到call才3ms.
同时,如使用hutool-all-5.3.8.jar的ThreadUtil.execAsyn方法效果也比较好,但没有restartAllCoreThreads()这个好,测试效果有9-14ms的消耗。
public static ThreadPoolExecutor getThreadPool() {
if (executorServer == null || executorServer.isShutdown() || executorServer.isTerminated()) {
synchronized (JzPreCheckUtil.class) {
if (executorServer == null || executorServer.isShutdown() || executorServer.isTerminated()) {
XxxConfig.isJzPrecheckEnabled(); //加载相关配置
log.info("corePoolSize="+XxxConfig.corePoolSize+" maximumPoolSize="+XxxConfig.maximumPoolSize+" keepAliveTime="+XxxConfig.keepAliveTime);
ThreadFactory threadFactory = new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
long t1=System.currentTimeMillis();
String threadName="jzThreadPool" + r.hashCode();
Thread newThread=new Thread(r, threadName);
long t2=System.currentTimeMillis();
log.info("创建线程="+threadName+" t1="+t1+" t2="+t2+" 时间差="+(t2-t1));
return newThread;
}
};
executorServer = new ThreadPoolExecutor(XxxConfig.corePoolSize, XxxConfig.maximumPoolSize, XxxConfig.keepAliveTime, TimeUnit.SECONDS, new SynchronousQueue(),threadFactory);
executorServer.prestartAllCoreThreads();
log.info("prestartAllCoreThreads 之后="+executorServer.getQueue().size()+" 线程活着的数量="+executorServer.getActiveCount()+
" 核心线程="+executorServer.getCorePoolSize()+" 最大线程="+executorServer.getMaximumPoolSize()+
" 线程数="+executorServer.getPoolSize());
}
}
}
log.info("queue 长度 后="+executorServer.getQueue().size()+" 线程活着的数量="+executorServer.getActiveCount()+
" 核心线程="+executorServer.getCorePoolSize()+" 最大线程="+executorServer.getMaximumPoolSize()+
" 线程数="+executorServer.getPoolSize());
return executorServer;
}
@Override
public Object call() throws Exception {
xxx
return out;
}
重写
ThreadPoolExecutor参考:
package com.stock.framework.precheck.test2;
import com.stock.framework.jzprecheck.JzConfig;
import org.slf4j.Logger;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
public class MyThreadPool2 extends ThreadPoolExecutor {
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
public static Logger log = XXConfig.log;
public MyThreadPool2(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
public MyThreadPool2(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
}
public MyThreadPool2(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
}
public MyThreadPool2(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
}
public MyThreadPool2 getThreadPool(){
// return XXXXUtil.getMyThreadPool();
return null;
}
@Override
public void execute(Runnable command) {
log.info("execute-11="+System.currentTimeMillis());
if (command == null){
throw new NullPointerException();
}
/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
*
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
*
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
*/
AtomicInteger ctl=getCtl();
int c = ctl.get();
if (workerCountOf(c) < getCorePoolSize()) {
if (addWorker(command, true))
return;
c = ctl.get();
}
log.info("execute-22="+System.currentTimeMillis());
BlockingQueue workQueue= (BlockingQueue) getPrivateValue(null,"workQueue");
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);
}
public void reject(Runnable command) {
RejectedExecutionHandler handler= (RejectedExecutionHandler) getPrivateValue(null,"handler");;
handler.rejectedExecution(command, this);
}
public int runStateOf(int c) { return c & ~CAPACITY; }
boolean isRunning(int c) {
return c < SHUTDOWN;
}
private boolean compareAndIncrementWorkerCount(int expect) {
AtomicInteger ctl=getCtl();
return ctl.compareAndSet(expect, expect + 1);
}
public Object getInstance(Object instance,String className,Object object) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class> enclosingClass = Class.forName(className);
Constructor constructor = enclosingClass.getDeclaredConstructors()[0];
constructor.setAccessible(true);
return constructor.newInstance(instance,object);
}
public Object getPrivateValue(Object obj ,String propName) {
Object value = null;
try {
// 通过属性获取对象的属性
//.getDeclaredFields() 获得某个类的所有声明的字段,即包括public、private和proteced但不包括父类申明字段
//.getClass() 是?个对象实例的?法,只有对象实例才有这个?法,具体的类是没有的
Field field = obj.getClass().getDeclaredField(propName);
// 对象的属性的访问权限设置为可访问
//允许获取实体类private的参数信息
field.setAccessible(true);
// 获取属性的对应的值
value = field.get(obj);
} catch (Exception e) {
e.printStackTrace();
log.error(e.toString());
return null;
}
return value;
}
public boolean addWorker(Runnable firstTask, boolean core) {
log.info("addWorker-1="+System.currentTimeMillis());
retry:
for (;;) {
AtomicInteger ctl=getCtl();
int c = ctl.get();
int rs = runStateOf(c);
BlockingQueue workQueue= (BlockingQueue) getPrivateValue(null,"workQueue");
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
log.info("addWorker-retry-1="+System.currentTimeMillis());
for (;;) {
log.info("addWorker-retry-2="+System.currentTimeMillis());
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? getCorePoolSize() : getMaximumPoolSize()))
return false;
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
log.info("addWorker-Worker-="+System.currentTimeMillis());
boolean workerStarted = false;
boolean workerAdded = false;
// Worker w = null;
Object w=null;
try {
// w = new Worker(firstTask);
w = getInstance(getThreadPool(),"java.util.concurrent.ThreadPoolExecutor$Worker",firstTask);
//final Thread t = w.thread;
final Thread t = (Thread)getPrivateValue(w,"thread");
log.info("addWorker-t-="+System.currentTimeMillis());
if (t != null) {
ReentrantLock mainLock11= (ReentrantLock) getPrivateValue(null,"mainLock");
final ReentrantLock mainLock = mainLock11;
log.info("addWorker-lock-="+System.currentTimeMillis());
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
AtomicInteger ctl=getCtl();
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
HashSet workers= (HashSet) getPrivateValue(null,"workers");
workers.add(w);
int s = workers.size();
if (s > getLargestPoolSize()){
// largestPoolSize = s;
setPrivateValue(null,"largestPoolSize",s);
}
workerAdded = true;
}
} finally {
mainLock.unlock();
}
log.info("addWorker-workerAdded="+workerAdded+" "+System.currentTimeMillis());
if (workerAdded) {
log.info("addWorker-t.start()= start before 状态="+t.getState()+" 优先级别="+t.getPriority()+" "+System.currentTimeMillis());
t.start();
log.info("addWorker-t.start()= start after 状态="+t.getState()+" 优先级别="+t.getPriority()+" "+System.currentTimeMillis());
workerStarted = true;
}
}
} catch (InstantiationException e) {
log.error(e.toString());
e.printStackTrace();
} catch (InvocationTargetException e) {
log.error(e.toString());
e.printStackTrace();
} catch (IllegalAccessException e) {
log.error(e.toString());
e.printStackTrace();
} catch (ClassNotFoundException e) {
log.error(e.toString());
e.printStackTrace();
} finally {
if (! workerStarted)
{
log.info("!workerStarted-t-="+System.currentTimeMillis());
// addWorkerFailed(w);
getPrivateMethodValue(getThreadPool(),"addWorkerFailed",w);
}
}
return workerStarted;
}
private void decrementWorkerCount() {
do {} while (! compareAndDecrementWorkerCount(getCtl().get()));
}
private boolean compareAndDecrementWorkerCount(int expect) {
return getCtl().compareAndSet(expect, expect - 1);
}
public AtomicInteger getCtl() {
/*if(executorServer==null){
// executorServer = JzPreCheckUtil.getThreadPool();
executorServer = getThreadPool();
}*/
AtomicInteger ctl= (AtomicInteger) getPrivateValue(getThreadPool(),"ctl");
return ctl;
}
int workerCountOf(int c) { return c & CAPACITY; }
public Object getPrivateValue(ThreadPoolExecutor executorServer ,String propName) {
Object value = null;
try {
if(executorServer==null){
// executorServer = JzPreCheckUtil.getThreadPool();
executorServer = getThreadPool();
}
// 通过属性获取对象的属性
//.getDeclaredFields() 获得某个类的所有声明的字段,即包括public、private和proteced但不包括父类申明字段
//.getClass() 是?个对象实例的?法,只有对象实例才有这个?法,具体的类是没有的
Field field = executorServer.getClass().getSuperclass().getDeclaredField(propName);
// 对象的属性的访问权限设置为可访问
//允许获取实体类private的参数信息
field.setAccessible(true);
// 获取属性的对应的值
value = field.get(executorServer);
} catch (Exception e) {
log.error(e.toString());
e.printStackTrace();
return null;
}
return value;
}
public void setPrivateValue(ThreadPoolExecutor executorServer, String propName,Object value) {
try {
if(executorServer==null){
// executorServer = JzPreCheckUtil.getThreadPool();
executorServer = getThreadPool();
}
// 通过属性获取对象的属性
//.getDeclaredFields() 获得某个类的所有声明的字段,即包括public、private和proteced但不包括父类申明字段
//.getClass() 是?个对象实例的?法,只有对象实例才有这个?法,具体的类是没有的
Field field = executorServer.getClass().getSuperclass().getDeclaredField(propName);
// 对象的属性的访问权限设置为可访问
//允许获取实体类private的参数信息
field.setAccessible(true);
// 获取属性的对应的值
field.set(executorServer,value);
} catch (Exception e) {
log.error(e.toString());
e.printStackTrace();
}
}
public Object getPrivateMethodValue(Object obj, String propName,Object val) {
//Object value = null;
try {
Class c = obj.getClass().getSuperclass();
// https://blog.csdn.net/qq_34626094/article/details/122687833
//getDeclaredMethod java.lang.NoSuchMethodException的异常原因在于调用getDeclaredMethod时要同时指定方法名和参数名,这两个不能错误。
Method method = c.getDeclaredMethod(propName,val.getClass());
method.setAccessible(true);
Object[] values = new Object[1];
values[0] = val;
return method.invoke(obj,values);
} catch (Exception e) {
log.error(e.toString());
return null;
}
}
}