首先明白线程池工作原理。
当线程池提交一个任务时,首先会判断核心线程数是否已满,没满就直接new一个核心线程去执行任务。
如果满了,就尝试加到任务队列里。
首先判断任务队列是否满了,没满就直接加,满了就去查看是否可以直接new一个非核心线程去执行任务。
先看线程池内线程数是否已达到最大,如果没达到,那就直接new一个非核心线程去执行任务,如果达到了那就根据饱和策略来拒绝任务。
工作原理就是这样,现在我们来尝试自定义线程,我们需要四样东西。
首先是测试类,没什么可说的。
重点的三样是:
任务类
worker执行类
线程池
任务类负责提交任务。
执行类用来执行任务所以它要掌握全部任务,所以它要有一个任务队列作为成员变量。
线程池,用来提交任务,内部通过worker来接收任务并执行。但这不代表他要有一个成员变量worker。
线程池内部有一个linkedlist来缓存任务并保证任务按顺序执行。当它new一个worker启用时,会把当前任务队列传进去。
上代码,注释很详细。
首先是任务类,实现Runnable接口。
package test5_19;
//自定义线程池的任务类
public class MyTask implements Runnable {
private int id;
public MyTask(int id){
this.id = id;
}
public void run(){
String name = Thread.currentThread().getName();
System.out.println("线程"+name+"即将运行任务"+id);
try {
Thread.sleep(200l);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程"+name+"完成了任务"+id);
}
public String toString(){
return "mytask{"+"id="+id+'}';
}
}
执行类Myworker 内部有缓存任务的队列,取出一个任务并执行
package test5_19;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
//执行类worker,用于执行任务,所以要拥有所有任务
public class MyWorker extends Thread {
//任务队列
private List<Runnable> task;
public MyWorker(String name,List<Runnable> task){
super(name);
this.task=task;
}
public void run(){
while (task.size()>0){
Runnable r = task.remove(0);
r.run();
}
}
}
class MyThreadPool{
private List<Runnable> task= Collections.synchronizedList(new LinkedList<>());
// Collections.synchronized()通过这个方法获得一个安全的linkedlist
private int num;//任务数量
private int corePoolSize;//核心线程数目
private int workSize;//任务队列里最多任务数
private int maxSize;//最大线程总数
public MyThreadPool(int corePoolSize,int workSize,int maxSize){
this.corePoolSize=corePoolSize;
this.maxSize=maxSize;
this.workSize=workSize;
}
public void submit(Runnable r){
if(task.size()>=workSize){
System.out.println("任务"+r+"被丢弃");
}else {
task.add(r);
execTask(r);
}
}
private void execTask(Runnable r){
if (num<corePoolSize){
new MyWorker("核心线程"+num,task).start();;
num++;
}else if(num<maxSize){
new MyWorker("非核心线程"+num,task).start();;
num++;
}else {
System.out.println("任务"+r+"被缓存了");
}
}
}
线程池,内部通过Worker来执行任务,它负责缓存任务,然后把任务队列提交给worker
class MyThreadPool{
private List<Runnable> task= Collections.synchronizedList(new LinkedList<>());
// Collections.synchronized()通过这个方法获得一个安全的linkedlist
private int num;//任务数量
private int corePoolSize;//核心线程数目
private int workSize;//任务队列里最多任务数
private int maxSize;//最大线程总数
public MyThreadPool(int corePoolSize,int workSize,int maxSize){
this.corePoolSize=corePoolSize;
this.maxSize=maxSize;
this.workSize=workSize;
}
public void submit(Runnable r){
if(task.size()>=workSize){
System.out.println("任务"+r+"被丢弃");
}else {
task.add(r);
execTask(r);
}
}
private void execTask(Runnable r){
if (num<corePoolSize){
new MyWorker("核心线程"+num,task).start();;
num++;
}else if(num<maxSize){
new MyWorker("非核心线程"+num,task).start();;
num++;
}else {
System.out.println("任务"+r+"被缓存了");
}
}
}
测试类
public class MyTest {
public static void main(String[] args) {
MyThreadPool pool=new MyThreadPool(2,3,5);
for (int i = 0; i < 15; i++) {
MyTask my = new MyTask(i);
pool.submit(my);
}
}
}