注意:但是在生产环境中,不合理的分配线程数,可能会造成严重的生成事故
Netty 核心线程数
//多线程版本Reactor实现类
public abstract class MultithreadEventLoopGroup extends
MultithreadEventExecutorGroup implements EventLoopGroup {
//IO事件处理线程数
private static final int DEFAULT_EVENT_LOOP_THREADS;
//IO事件处理线程数默认值为CPU核数的两倍
static {
DEFAULT_EVENT_LOOP_THREADS = Math.max(1,
SystemPropertyUtil.getInt("io.netty.eventLoopThreads",
Runtime.getRuntime().availableProcessors() * 2));
}
/**
*构造器
*/
protected MultithreadEventLoopGroup(int nThreads,
ThreadFactory threadFactory, Object... args) {
super(nThreads == 0?
DEFAULT_EVENT_LOOP_THREADS : nThreads, threadFactory, args);
}
}
总结
如果是IO密集型任务核心数=CPU核数的两倍
参考案例
// 省略import
public class ThreadUtil
{
//CPU核数
private static final int CPU_COUNT =
Runtime.getRuntime().availableProcessors();
//IO处理线程数
private static final int IO_MAX = Math.max(2, CPU_COUNT * 2);
/**
* 空闲保活时限,单位秒
*/
private static final int KEEP_ALIVE_SECONDS = 30;
/**
* 有界队列size
*/
private static final int QUEUE_SIZE = 128;
//懒汉式单例创建线程池:用于IO密集型任务
private static class IoIntenseTargetThreadPoolLazyHolder
{
//线程池: 用于IO密集型任务
private static final ThreadPoolExecutor EXECUTOR =
new ThreadPoolExecutor(
IO_MAX, //CPU核数*2
IO_MAX, //CPU核数*2
KEEP_ALIVE_SECONDS,
TimeUnit.SECONDS,
new LinkedBlockingQueue(QUEUE_SIZE),
new CustomThreadFactory("io"));
static
{
EXECUTOR.allowCoreThreadTimeOut(true);
//JVM关闭时的钩子函数
Runtime.getRuntime().addShutdownHook(
new ShutdownHookThread("IO密集型任务线程池",
new Callable<Void>()
{
@Override
public Void call() throws Exception
{
//优雅地关闭线程池
shutdownThreadPoolGracefully(EXECUTOR);
return null;
}
}));
}
}
}
CPU密集型任务也叫计算密集型任务,其特点是要进行大量计算而需要消耗CPU资源,比如计算圆周率、对视频进行高清解码等。CPU密集型任务虽然也可以并行完成,但是并行的任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以要最高效地利用CPU,CPU密集型任务并行执行的数量应当等于CPU的核心数。
案例
// 省略import
public class ThreadUtil
{
//CPU核数
private static final int CPU_COUNT =
Runtime.getRuntime().availableProcessors();
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT;
//懒汉式单例创建线程池:用于CPU密集型任务
private static class CpuIntenseTargetThreadPoolLazyHolder
{
//线程池:用于CPU密集型任务
private static final ThreadPoolExecutor EXECUTOR =
new ThreadPoolExecutor(
MAXIMUM_POOL_SIZE,
MAXIMUM_POOL_SIZE,
KEEP_ALIVE_SECONDS,
TimeUnit.SECONDS,
new LinkedBlockingQueue(QUEUE_SIZE),
new CustomThreadFactory("cpu"));
static
{
EXECUTOR.allowCoreThreadTimeOut(true);
//JVM关闭时的钩子函数
Runtime.getRuntime().addShutdownHook(
new ShutdownHookThread("CPU密集型任务线程池",
new Callable<Void>()
{
@Override
public Void call() throws Exception
{
//优雅地关闭线程池
shutdownThreadPoolGracefully(EXECUTOR);
return null;
}
}));
}
}
// 省略不相干代码
}
混合型任务既要执行逻辑计算,又要进行大量非CPU耗时操作(如RPC调用、数据库访问、网络通信等),所以混合型任务CPU的利用率不是太高,非CPU耗时往往是CPU耗时的数倍。比如在Web应用中处理HTTP请求时,一次请求处理会包括DB操作、RPC操作、缓存操作等多种耗时操作。一般来说,一次Web请求的CPU计算耗时往往较少,大致在100~500毫秒,而其他耗时操作会占用500~1000毫秒,甚至更多的时间。
最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1) * CPU核数
等待时间所占的比例越高,需要的线程就越多;CPU耗时所占的比例越高,需要的线程就越少。
获取所有线程的CPU执行时间
ThreadMXBean tmbean = ManagementFactory.getThreadMXBean();
tmbean.setThreadContentionMonitoringEnabled(true);
long[] allThread = tmbean.getAllThreadIds();
获取到id数组之后,遍历线程id,通过getThreadCpuTime(long id)等获取线时间
获取等待、阻塞时间等
ThreadInfo info = tmbean.getThreadInfo(threadId);
package Time;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
/**
* @description:
* @author: shu
* @createDate: 2022/11/1 13:45
* @version: 1.0
*/
public class TimeThreadTest {
public static void main(String[] args) {
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
bean.setThreadContentionMonitoringEnabled(true);
long[] allThread = bean.getAllThreadIds();
if (allThread.length > 0) {
for (long threadId : allThread) {
ThreadInfo info = bean.getThreadInfo(threadId);
Long userTime = info.getWaitedTime();
System.out.println("ThreadId:" + info.getThreadId() +" "+ "ThreadName:" + info.getThreadName() +" "+ "ThreadState:" + info.getThreadState() +" "+"userTime:" + userTime.toString());
}
}
}
}
用例
// 省略import
public class ThreadUtil
{
private static final int MIXED_MAX = 128; //最大线程数
private static final String MIXED_THREAD_AMOUNT = "mixed.thread.amount";
//懒汉式单例创建线程池:用于混合型任务
private static class MixedTargetThreadPoolLazyHolder
{
//首先从环境变量 mixed.thread.amount 中获取预先配置的线程数
//如果没有对 mixed.thread.amount进行配置,就使用常量 MIXED_MAX作为线程数
private static final int max =
(null != System.getProperty(MIXED_THREAD_AMOUNT)) ?
Integer.parseInt(System.getProperty(MIXED_THREAD_AMOUNT))
: MIXED_MAX;
//线程池:用于混合型任务
private static final ThreadPoolExecutor EXECUTOR =
new ThreadPoolExecutor(
max,
max,
KEEP_ALIVE_SECONDS,
TimeUnit.SECONDS,
new LinkedBlockingQueue(QUEUE_SIZE),
new CustomThreadFactory("mixed"));
static
{
EXECUTOR.allowCoreThreadTimeOut(true);
//JVM关闭时的钩子函数
Runtime.getRuntime().addShutdownHook(
new ShutdownHookThread("混合型任务线程池", new Callable<Void>()
{
@Override
public Void call() throws Exception
{
//优雅地关闭线程池
shutdownThreadPoolGracefully(EXECUTOR);
return null;
}
}));
}
}
}