简单易懂-线程池
程序员文章站
2023-12-23 13:55:22
...
为什么要线程池
频繁的创建和销毁线程会降低系统效率,寻求一种线程复用的方式,那么可以使用缓存的策略,也就是使用线程池。简单说就是线程复用,提高效率,节约资源。
线程池是怎样的
线程池的核心类:ThreadPoolExecutor
ThreadPoolExecutor、AbstractExecutorService、ExecutorService和Executor
Executor:一个顶层接口,在它里面只声明了一个方法execute(Runnable),返回值为void,参数为Runnable类型,从字面意思可以理解,就是用来执行传进去的任务的;
ExecutorService接口:继承了Executor接口,并声明了一些方法:submit、invokeAll、invokeAny以及shutDown等;
抽象类AbstractExecutorService:实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法;
ThreadPoolExecutor: 继承了类AbstractExecutorService。
ThreadPoolExecutor的主要方法:
execute() //可以向线程池提交一个任务,交由线程池去执行。
submit() //用来向线程池提交任务的,但是它和execute()方法不同,它能够返回任务执行的结果
shutdown()
shutdownNow()// shutdown()和shutdownNow()是用来关闭线程池的。
ThreadPoolExecutor类中重要的成员变量:
private volatile long keepAliveTime; //线程存活时间
private volatile boolean allowCoreThreadTimeOut;//是否允许为核心线程设置存活时间
private volatile int corePoolSize; //核心池的大小(即线程池中的线程数目大于这个参数时,提交的任务会被放进任务缓存队列)
private volatile int maximumPoolSize; //线程池最大能容忍的线程数
private volatile int poolSize; //线程池中当前的线程数
private volatile int largestPoolSize; //记录线程池中曾经有过的最大线程数目,跟线程池的容量没有任何关系。
线程池的使用
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
public class ThreadTest
{
public static void main(String[] args)
{
//ExecutorService threadPool = Executors.newFixedThreadPool(10);一般用这种方式来创建线程池,下面的创建方式有比较好用的方法。
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS,//最大承受的线程数为10,下面队列的长度为6,如果创建的线程大于16就会发生错误,因为所有的线程都存活着,超容了。
// public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue);
new ArrayBlockingQueue<Runnable>(6));//当线程数大于corePoolSize时进入等待的队列
for(int i = 0;i<16;i++){
MyThread myThread1 = new MyThread(i);
threadPool.execute(myThread1);
System.out.println("线程池中线程数目:"+threadPool.getPoolSize()+",队列中等待执行的任务数目:"+
threadPool.getQueue().size());
}
threadPool.shutdown();
}
}
class MyThread implements Runnable
{
private int taskNum;
public MyThread(int num){
this.taskNum = num;
}
@Override
public void run(){
System.out.println("正在执行task:"+taskNum);
try{
Thread.currentThread().sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("task"+taskNum+" 执行完毕");
}
}
结果
---------- java运行 ----------
线程池中线程数目:1,队列中等待执行的任务数目:0
正在执行task:0
线程池中线程数目:2,队列中等待执行的任务数目:0
正在执行task:1
线程池中线程数目:3,队列中等待执行的任务数目:0
正在执行task:2
线程池中线程数目:4,队列中等待执行的任务数目:0
正在执行task:3
线程池中线程数目:5,队列中等待执行的任务数目:0
线程池中线程数目:5,队列中等待执行的任务数目:1
线程池中线程数目:5,队列中等待执行的任务数目:2
线程池中线程数目:5,队列中等待执行的任务数目:3
线程池中线程数目:5,队列中等待执行的任务数目:4
线程池中线程数目:5,队列中等待执行的任务数目:5
线程池中线程数目:5,队列中等待执行的任务数目:6
正在执行task:4
线程池中线程数目:6,队列中等待执行的任务数目:6
正在执行task:11
线程池中线程数目:7,队列中等待执行的任务数目:6
正在执行task:12
线程池中线程数目:8,队列中等待执行的任务数目:6
正在执行task:13
线程池中线程数目:9,队列中等待执行的任务数目:6
正在执行task:14
线程池中线程数目:10,队列中等待执行的任务数目:6
正在执行task:15
task1 执行完毕
task0 执行完毕
正在执行task:5
task2 执行完毕
task3 执行完毕
正在执行task:6
task4 执行完毕
正在执行task:7
正在执行task:8
正在执行task:9
task11 执行完毕
正在执行task:10
task12 执行完毕
task13 执行完毕
task14 执行完毕
task15 执行完毕
task8 执行完毕
task10 执行完毕
task6 执行完毕
task9 执行完毕
task5 执行完毕
task7 执行完毕
输出完成 (耗时 4 秒) - 正常终止