可以理解为一个池子里有很多备用线程,能够优化频繁创建销毁线程的场景。
线程池的创建
ExecutorService service= Executors.newFixedThreadPool(4);
//线程池对象不是new出来的,而是通过专门的方法返回对象
我们知道new关键字会触发构造方法,从而初始化对象,构造方法要求方法名必须与类名相同,有点时候我们希望一个对象有不同的构造方法,这个时候不同的构造方法只能采用方法的重载,方法重载要求参数的类型或者个数必须不同,这就有一定的局限性。此时我们引入工厂模式。在工厂模式里,设计一个类里面有许多静态的普通方法,我们调用这些普通方法完成对象的构造,就没有什么限制了。
这里的Executors就是一个工厂类,它点出来后面的就是许多的工厂方法
上述工厂方法其实是对ThreaPoolExecutor类的封装,这个类功能丰富,有很多参数,标准库上述的几个方法其实就是给这个类填写了不同的参数来构造线程池。
参数介绍
public ThreadPoolExecutor(int corePoolSize,//核心线程数
int maximumPoolSize,//最大线程数
long keepAliveTime,//线程存活最长时间
TimeUnit unit,//时间单位,s,ms,us...
BlockingQueue<Runnable> workQueue,//阻塞队列,用来存放线程池中
的任务
ThreadFactory threadFactory,//工厂模式的体现,使用ThreadFactory
作为工厂类
RejectedExecutionHandler handler)//拒绝策略
当线程池里的任务数达到上限,再往里面添加任务时,对于不同的拒绝策略会长生不同的效果。
ThreadPoolExecutor.AbortPolicy:直接抛出一个异常。
ThreadPoolExecutor.CallerRunsPolicy:新添加的任务有添加任务的线程执行。
ThreadPoolExecutor.DiscardOldestPolicy:抛弃队列中最老的任务。
ThreadPoolExecutor.DiscardPolicy:抛弃新加的任务。
此外,线程池的线程数目设置必须是根据实际项目测试来设定的,要结合实际代码。
对于一个线程来说,执行的代码主要有两类
1cpu密集型:代码里主要是逻辑/算数运算,线程数小于逻辑cpu核心数。
2 IO密集型:代码主要是IO操作,不吃cpu,所以线程数可以设置为超过cpu核心数。
线程池的创建
在 Java 标准库中,线程池的创建:
1 Executors 工厂方法:Executors 类提供了一系列静态工厂方法来创建不同类型的线程池,如 newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor 等。这些工厂方法提供了一些常见线程池配置的快捷方式,但是在某些情况下可能并不适合自定义需求。
2 ThreadPoolExecutor 构造函数:可以直接使用 ThreadPoolExecutor 的构造函数来创建线程池,这允许你对线程池的各种参数进行精细调整,如核心线程数、最大线程数、工作队列类型、拒绝策略等。
虽然有多种方式可以创建线程池,但建议根据具体的需求来选择合适的创建方式,以及对线程池参数进行合理的配置。
1使用工厂类
import java.util.concurrent.*;
//使用线程池
public class test {
public static void main(String[] args) {
ExecutorService service= Executors.newFixedThreadPool(10);
//线程池对象不是new出来的,而是通过专门的方法返回对象
for (int i = 0; i < 10; i++) {
int id=i;
service.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("Task"+id+"is completed");
}
});
}
service.shutdown();
}
}
2使用ThreadPoolExecutor构造函数
import java.util.concurrent.*;
public class test {
public static void main(String[] args) {
int corePoolSize = 5;
int maximumPoolSize = 10;
long keepAliveTime = 5000;
TimeUnit unit = TimeUnit.MILLISECONDS;
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(10);
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy(); // 使用丢弃策略
ThreadPoolExecutor executor = new ThreadPoolExecutor(
corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
for (int i = 0; i < 20; i++) {
int id=i;
executor.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task " + id+ " is completed");
}
});
}
executor.shutdown();
}
}