文件链接:
提取码:xyem
自定义线程池 - 实现步骤
1、先创建一个任务类 - MyTask
代码示例:
package com.zhoulz.demo01;
/**
* 需求:
* 自定义线程池练习,这是任务类,需要实现Runnable接口;
* 包含任务编号,每一个任务执行时间设计为0.2秒
*/
public class MyTask implements Runnable{
// 手动的加上一个任务编号
private int id;
// 由于run()方法是重写的方法,所以不能加参数(比如加id),怎么办?
// : id这个属性初始化可以利用构造方法完成
public MyTask(int id) {
this.id = id;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println("线程:"+name+"即将执行任务:"+id);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程:"+name+"完成了任务:"+id);
}
@Override
public String toString() {
return "MyTask{" +
"id=" + id +
'}';
}
}
2、接着,创建一个线程类 - MyWorker
代码示例:
package com.zhoulz.demo01;
import java.util.List;
/**
* 需求:
* 编写一个线程类,需要继承Thread类,设计一个属性,用于保存现成的名字;
* 设计一个集合,用于保存所有的任务,后面用于执行。
*/
public class MyWorker extends Thread{
private String name; // 保存线程的名字
private List<Runnable> tasks;
// 利用构造方法,给成员变量赋值
public MyWorker(String name, List<Runnable> tasks) {
super(name);
this.tasks = tasks;
}
@Override
public void run() {
// 判断集合中是否有任务,只要有,就一直执行
while (tasks.size() > 0){
// 把第一个任务移除出来
Runnable r = tasks.remove(0);
// 然后去执行这个任务
r.run();
}
}
}
3、然后,创建一个线程池类 - MyThreadPool
代码示例:
package com.zhoulz.demo01;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* 这是自定义的线程池类;
*
* 成员变量:
* 1.任务队列 - 集合 (需要控制线程安全问题)
* 2.当前线程数量
* 3.核心线程数量
* 4.最大线程数量
* 5.任务队列的长度
* 成员方法:
* 1.提交任务:
* 将任务添加到集合中,需要判断是否超出了任务队列的总长度
* 2.执行任务:
* 判断当前线程的数量,决定创建核心线程还是非核心线程
*/
public class MyThreadPool {
// 1.任务队列 - 集合 (需要控制线程安全问题)
//private List<Runnable> tasks = new LinkedList<>(); // LinkedList 不能保证线程的安全
private List<Runnable> tasks = Collections.synchronizedList(new LinkedList<>());
// 2.当前线程数量
private int num;
// 3.核心线程数量
private int corePoolSize;
// 4.最大线程数量
private int maxSize;
// 5.任务队列的长度
private int workSize;
// 需要带参的构造方法 —— 带后面3个参数即可
public MyThreadPool(int corePoolSize, int maxSize, int workSize) {
this.corePoolSize = corePoolSize;
this.maxSize = maxSize;
this.workSize = workSize;
}
// 1.提交任务:(并执行任务,执行任务的方法另行创建了)
public void submit(Runnable r){
// 判断当前集合中任务的数量,是否超出了最大任务数量
if (tasks.size() >= workSize){
System.out.println("任务:"+ r + "被丢弃了。。。");
}else {
tasks.add(r);
// 然后执行任务
execTask(r);
}
}
// 2.执行任务:
private void execTask(Runnable r) {
// 判断当前线程池中的线程总数量,是否超越了核心线程数量:
// 如果没超出,则直接创建一个新的线程来处理任务;
// 如果超出了,则还要进一步判断是否超出了最大线程数量:
// 如果没有超出最大线程数量,则要去创建非核心线程
// 如果超出最大线程数量,则要使其处于等待状态,即在任务缓存队列缓存一会
if (num < corePoolSize){
// 如果小于,则直接去创建线程
new MyWorker("核心线程:"+ num,tasks).start();
num ++;
}else if (num < maxSize){
new MyWorker("非核心线程:"+num,tasks).start();
num ++;
}else {
System.out.println("任务:"+ r + "被缓存了。。。");
}
}
}
4、最后,创建测试类 - MyTest
代码示例:
package com.zhoulz.demo01;
/**
* 测试类:
* 1、创建线程池类对象;
* 2、提交多个任务 —— 采用循环的方式
*/
public class MyTest {
public static void main(String[] args) {
// 1、创建线程池类对象;
MyThreadPool pool = new MyThreadPool(2,4,20);
// 2、提交多个任务 —— 采用循环的方式
for (int i = 0; i < 10; i++) {
// 3、创建任务对象,并提交给线程池
MyTask myTask = new MyTask(i);
pool.submit(myTask);
}
}
}
运行结果:
可以在测试类中改变提交的任务数,运行以作比较。