1线程池是什么?
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。对于一个队列的任务,如果将每个任务都创建一个进行任务处理,那有多少个任务就会创建多少个线程,每个线程在其生命周期只能执行一次对应的任务,并且重复的创建销毁线程会有额外的资源消耗,进而影响缓存局部性和整体性能。
而线程池中维护着多个线程,这些线程等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。
2线程池构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
在构造线程池函数时,需要传入核心线程个数,最大线程个数,等待时间,参数时间单位以及任务队列。
corePoolSize - 核心线程数是主要工作的线程个数,即使空闲时仍保留在池中的线程数。
maximumPoolSize - 线程池中允许存在的最大线程数。
keepAliveTime - 当线程数大于核心时,这是多余的空闲线程在终止之前等待新任务的最大时间。
unit - keepAliveTime参数的时间单位。
workQueue - 在执行任务之前用于保存任务的队列。 该队列将仅保存execute方法提交的Runnable任务
3制作一个线程池
新建一个ThreadPool类,添加核心线程数,任务队列容量,和装线程与任务的集合
// 核心线程数量
int Defaultworkthrednum;
// 任务队列容量
int Defaulttasknum ;
static List<WorkThread> cthreads;// 线程集合
static BlockingQueue<Runnable> taskQueue;// 任务阻塞队列
ThreadPool(int Defaultworkthrednum , int Defaulttasknum){
cthreads = new ArrayList<>();
taskQueue = new ArrayBlockingQueue<>(Defaulttasknum);
this.Defaulttasknum=Defaulttasknum;
this.Defaultworkthrednum=Defaultworkthrednum;
}
添加一个启动线程的方法
void startPool() {
for (int i = 0; i < Defaultworkthrednum; i++) {
WorkThread workThread = new WorkThread("No." + i,i);
workThread.start();
cthreads.add(workThread);
}
}
添加一个向任务队列中添加任务的方法
void addTask(Runnable task) {
try {
taskQueue.put(task);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
添加一个停止线程工作的方法
void stopPool() {
for (int i = 0; i <cthreads.size() ; i++) {
System.out.println(cthreads.get(i).getName()+" stop pool");
cthreads.get(i).isStop=true;
cthreads.get(i).interrupt();
}
}
创建一个工作线程的类
public class WorkThread extends Thread{
String name;
int id;
public WorkThread(String s,int id) {
this.name=s;
this.id=id;
}
boolean isStop = false;
@Override
public void run() {
System.out.println("线程"+name+"开始工作");
while (!isStop) {
System.out.println("任务池中还有:" + ThreadPool.taskQueue.size());
try {
if(TaskE.doneJob>=500){
}else {
Runnable runnable = ThreadPool.taskQueue.take();
System.out.println("线程"+name+"获取了"+runnable.toString());
runnable.run();
System.gc();
}
// 获取任务
} catch (InterruptedException e) {
//e.printStackTrace();
}
}
}
}
用主程序测试线程池
public class TaskE {
static int mm = 0;
static int doneJob=0;
static boolean wa = true;
public static void main(String[] args) {
int i = 0;
ThreadPool tp = new ThreadPool(5,10);
Thread t = new Thread(new Runnable(){
int num = 0;
@Override
public void run() {
while (num<20) {
num++;
mm=num;
tp.addTask(new Runnable() {
String taskName = "任务" + num + "号!";
@Override
public void run() {
System.out.println(taskName + "处理完成!!");
doneJob++;
}
@Override
public String toString() {
return taskName;
}
});
System.err.println("任务ADD"+num);
}
}
});
t.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
tp.startPool();
while(doneJob <19){
System.out.print("");
}
tp.stopPool();
}
}
最后输出结果
任务ADD1
任务ADD2
任务ADD3
任务ADD4
任务ADD5
任务ADD6
任务ADD7
任务ADD8
任务ADD9
任务ADD10
线程No.0开始工作
线程No.2开始工作
线程No.1开始工作
任务池中还有:10
线程No.3开始工作
任务池中还有:10
线程No.4开始工作
任务池中还有:10
线程No.1获取了任务2号!
任务池中还有:9
线程No.4获取了任务4号!
任务4号!处理完成!!
任务池中还有:9
任务ADD11
任务ADD12
任务ADD13
任务ADD14
任务ADD15
任务ADD16
线程No.3获取了任务5号!
任务5号!处理完成!!
线程No.0获取了任务1号!
任务1号!处理完成!!
任务池中还有:10
线程No.0获取了任务6号!
任务6号!处理完成!!
任务池中还有:10
线程No.3获取了任务7号!
任务7号!处理完成!!
任务池中还有:9
任务池中还有:10
线程No.3获取了任务9号!
任务9号!处理完成!!
任务2号!处理完成!!
任务池中还有:10
任务ADD17
任务ADD18
任务ADD19
任务ADD20
线程No.3获取了任务10号!
任务10号!处理完成!!
线程No.2获取了任务3号!
任务池中还有:10
线程No.3获取了任务11号!
任务11号!处理完成!!
任务池中还有:10
线程No.1获取了任务12号!
任务12号!处理完成!!
线程No.4获取了任务8号!
任务8号!处理完成!!
任务池中还有:10
线程No.0获取了任务13号!
任务13号!处理完成!!
任务池中还有:7
任务池中还有:8
线程No.4获取了任务15号!
任务池中还有:8
线程No.1获取了任务16号!
任务16号!处理完成!!
任务池中还有:8
线程No.3获取了任务17号!
任务17号!处理完成!!
任务3号!处理完成!!
任务池中还有:3
任务池中还有:3
线程No.1获取了任务19号!
任务19号!处理完成!!
任务15号!处理完成!!
线程No.0获取了任务14号!
任务14号!处理完成!!
任务池中还有:1
线程No.4获取了任务20号!
任务20号!处理完成!!
任务池中还有:1
线程No.3获取了任务18号!
任务18号!处理完成!!
任务池中还有:3
任务池中还有:0
任务池中还有:0
任务池中还有:1
Thread-1 stop pool
Thread-2 stop pool
Thread-3 stop pool
Thread-4 stop pool
Thread-5 stop pool