java使用线程池需要什么步骤 线程池的简单实现
"作为一名Java开发者,是否曾经遇到过多线程并发的问题?线程数量过多时,会导致资源浪费,应用性能下降,甚至发生线程死锁的情况。那么,有没有一种方法可以有效地管理线程,避免这些问题呢?答案是肯定的,那就是线程池。在本文中,我们将通过Java的角度,探讨线程池的奥妙,深入了解线程池的优势,学习如何使用线程池实现多线程并发。"
线程池是如何创建的?JAVA中创建线程池主要有两类方法,一类是通过Executors工厂类提供的方法,该类提供了4种不同的线程池可供使用。另一类是通过ThreadPoolExecutor类进行自定义创建。
Executors工厂类
// 五种线程池:
// ExecutorService threadPool = null;
// threadPool = Executors.newCachedThreadPool();//有缓冲的线程池,线程数 JVM 控制
// threadPool = Executors.newFixedThreadPool(3);//固定大小的线程池
// threadPool = Executors.newScheduledThreadPool(2); // 具有延时,定时功能
// threadPool = Executors.newSingleThreadExecutor();//单线程的线程池,只有一个线程在工作
// threadPool = new ThreadPoolExecutor();//默认线程池,可控制参数比较多
private static void createCachedThreadPool() {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i ) {
final int index = i;
executorService.execute(() -> {
// 获取线程名称,默认格式:pool-1-thread-1
System.out.println(DateUtil.now() " " Thread.currentThread().getName() " " index);
// 等待2秒
sleep(2000);
});
}
}
ThreadPoolExecutor类
ThreadPoolExecutor提供构造方法,需要自己设置具体的参数,更加灵活
public ThreadPoolExecutor(int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大工作线程
long keepAliveTime, // 存活时间,线程没有任务执行时最多保持多久时间会终止。
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 工作队列
ThreadFactory threadFactory, // 线程工厂,主要用来创建线程,默及正常优先级、非守护线程。
RejectedExecutionHandler handler // 拒绝策略,当创建新线程使线程数大于最大线程的情况下,会执行
) {
// 省略...
}
- corePoolSize 核心线程数 核心线程数,线程池中始终存活的线程数。
- BlockingQueue 工作队列 workQueue = new ArrayBlockingQueue<>(5);//基于数组的先进先出队列,有界 workQueue = new LinkedBlockingQueue<>();//基于链表的先进先出队列,无界 workQueue = new SynchronousQueue<>();//无缓冲的等待队列,无界
- threadFactory 线程工厂 用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的。线程设置更有意义的名字。使用开源框架 guava 提供的 ThreadFactoryBuilder 可以快速给线程池里的线程设置有意义的名字,代码如下:
new ThreadFactoryBuilder().setNameFormat("XX-task-%d").build();
- handler 拒绝策略,拒绝处理任务时的策略,4种可选,默认为AbortPolicy。
参数 描述 AbortPolicy 拒绝并抛出异常 CallerRunsPolicy 只用调用者所在线程来运行任务 DiscardOldestPolicy 抛弃队列头部(最旧)的一个任务,并执行当前任务。 DiscardPolicy 抛弃当前任务。
RejectedExecutionHandler rejected = null;
rejected = new ThreadPoolExecutor.AbortPolicy();//默认,队列满了丢任务抛出异常
rejected = new ThreadPoolExecutor.DiscardPolicy();//队列满了丢任务不异常
rejected = new ThreadPoolExecutor.DiscardOldestPolicy();//将最早进入队列的任务删,之后再尝试加入队列
rejected = new ThreadPoolExecutor.CallerRunsPolicy();//如果添加到线程池失败,那么主线程会自己去执行
- 主线程提交任务到线程池,如果当前线程数小于核心线程数,创建新的线程用于执行任务,如果不是,下一步。
- 此时核心线程已满,再判断工作队列存放的线程数是否满了,如果没有满,则放入工作队列,如果不是,下一步。
- 此时工作队列满了,再看当前线程数是否等于最大线程数,如果是的话,执行拒绝策略,如果不是,创建新的线程,执行任务。
- cpu密集型 maximumPoolSize = n*cpu 1
- io密集型 maximumPoolSize = 2 * n * cpu
可以通过调用线程池的 shutdown 或 shutdownNow 方法来关闭线程池。 相同点:遍历所有的工作线程,然后interrupt掉线程 不同点:shutdown 调用后,不再接受新的任务,但是会等待正在运行的线程,停止没有执行任务的线程。 shutdownNow 调用后会尝试停止正在运行或暂停任务的线程。
原创不易,麻烦点个赞再走呗!
,免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com