编写一个线程池
线程池创建方法
(1)newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务
(2)newCachedThreadPool创建一个可缓存线程池
(3)newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数
(4)newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行
但在实际开发中以上方法并不推荐使用
根据阿里巴巴Java开发手册中并发处理中提及到有关线程池内容如下:
线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
使用线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。
线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式可以更加明确线程池的运行规则,规避资源耗尽的风险。
使用Executors返回的线程池对象的弊端
(1)FixedThreadPool和SingThreadPool;允许的请求队列长度为Integer.Max_VALUE,可能会堆积大量的请求,从而导致OOM;
(2)CachedThreadPool和ScheduledThreadPool ;允许的创建线程数量为Integer.Max_VALUE,可能会创建大量的线程,从而导致OOM。
代码实现
public class MyThreadPoolDemo {
/*
* ThreadPoolExecutor(int corePoolSize, 核心线程数
* int maximumPoolSize, 最大线程数 long
* keepAliveTime, 线程空闲时间 TimeUnit unit, 参数keepAliveTime的时间单位,共7种取值,
* {
* TimeUnit.DAYS; //天 TimeUnit.HOURS; //小时 TimeUnit.MINUTES; //分钟
* TimeUnit.SECONDS; //秒 TimeUnit.MILLISECONDS; //毫秒 TimeUnit.MICROSECONDS; //微妙
* TimeUnit.NANOSECONDS; //纳秒
* }
* BlockingQueue<Runnable> workQueue) 阻塞队列
*/
/*
* 最大数
* CPU
* 密集型: CPU核数+1个线程的线程池 IO
* 密集型: 1.CPU*2 2.CPU核数/(1-阻塞系数)
* 阻塞系数 0.8-0.9
*/
public static void main(String[] args) {
ExecutorService threadPool = new ThreadPoolExecutor(2, 5, 1L, TimeUnit.SECONDS, // 时间单位
new LinkedBlockingQueue<>(3), // 阻塞队列
Executors.defaultThreadFactory(),
/*
* 拒接策略 AbortPolicy()
* 最大+阻塞【java.util.concurrent.RejectedExecutionException】
* CallerRunsPolicy() 超过的回退给调用者(不会出异常)
* DiscardOldestPolicy() 抛弃等待时间最久,然后把当前任务队列中尝试再提交
* DiscardPolicy() 直接丢弃
*/
new ThreadPoolExecutor.DiscardPolicy());
try {
for (int i = 1; i <= 11; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "\t 办理业务");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
// newCachedThreadPool
public static void CachedThreadTest() {
一池N个线程
ExecutorService threadPool = Executors.newCachedThreadPool();
// 模拟10个用户来办理业务,每个用户就是一个来自外部的请求线程
try {
for (int i = 1; i <= 10; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "\t 办理业务!");
});
}
} catch (Exception e) {
// TODO: handle exception
} finally {
threadPool.shutdown();
}
}
// newSingleThreadExecutor()
public static void SingleThreadTest() {
// 一池1个线程
ExecutorService threadPool = Executors.newSingleThreadExecutor();
// 模拟10个用户来办理业务,每个用户就是一个来自外部的请求线程
try {
for (int i = 1; i <= 10; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "\t 办理业务!");
});
}
} catch (Exception e) {
// TODO: handle exception
} finally {
threadPool.shutdown();
}
}
// newFixedThreadPool(5)
public static void FixedThreadPoolTest() {
// 一池5个处理线程
ExecutorService threadPool = Executors.newFixedThreadPool(5);
// 模拟10个用户来办理业务,每个用户就是一个来自外部的请求线程
try {
for (int i = 1; i <= 10; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "\t 办理业务!");
});
}
} catch (Exception e) {
// TODO: handle exception
} finally {
threadPool.shutdown();
}
}
}