1. 线程池概念
创建Java线程需要给线程分配堆栈内存以及初始化内存,还需要进行系统调用,频繁地创建和销毁线程会大大降低系统的运行效率,采用线程池来管理线程有以下好处:
- 提升性能:线程池能独立负责线程的创建、维护和分配
- 线程管理:每个Java线程池会保持一些基本的线程统计信息,对线程进行有效管理
在开发中,由于频繁创建和停止线程会导致效率低下,我们可以创建一个线程池,然后创建任务提交给线程池,由线程池创建线程去执行任务,在线程池中的线程在执行完任务之后会被回收,用于下一个任务。我们还可以指定线程池的大小,如果没有可用线程,则任务会进入等待状态。
2.线程池的代码实现
1.创建线程池
Executors:线程池的工具类通过调用方法返回不同类型的线程池对象。
2.提交任务
使用submit()方法,参数可以是Runnable接口或者Callable接口的实现类,也可以是匿名内部类或者Lambda表达式
3.所有的任务全部执行完毕,关闭线程池
shutdown()方法关闭线程池
public class ThreadPoolDemo {
public static void main(String[] args) {
//1.创建线程池的对象
ExecutorService ThreadPool = Executors.newCachedThreadPool();
//2.提交任务
// 可以是Runnable接口或者Callable接口的实现类。 // 同样可以使用匿名内部类或者Lambda表达式
ThreadPool.submit(()->{
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " : "+i);
}
});
// 实现类
ThreadPool.submit(new MyRunnable());
//3.销毁线程池
// 在实际开发中,线程池一般是不会销毁的 ThreadPool.shutdown();
}
}
MyRunnable类
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
自定义线程池对象
在创建对象时,构造方法最多有七个参数
拒绝策略
public static void main(String[] args) {
new ThreadPoolExecutor(
3, // 核心线程数量
6, // 最大线程数量
60, //空闲线程最大存活时间
TimeUnit.SECONDS, // 存活时间单位
new ArrayBlockingQueue<>(3), // 等待队列
Executors.defaultThreadFactory(), // 创建线程工厂
new ThreadPoolExecutor.AbortPolicy() // 任务的拒绝策略
);
}
要点:
1.等待队列需要自己创建
2.需要传入线程工厂,其是Executors工具类中的静态方法
3.拒绝策略是ThreadPoolExecutor类中的内部类对象
线程池大小多少合适
1.什么是最大并行数?
CPU线程数就是最大并行数,但是一般情况下操作系统不会将所有线程全部给一个程序使用,所以最好的办法是通过代码获取最大并行数
Runtime.getRuntime().availableProcessors()