模拟jdk线程池实现,自己开发一个线程池
作用
1、线程池能重用线程对象,减少创建和销毁线程时资源的开销;
2、能控制最大并发数;
3、线程池可以对线程进行管理,如定时、定期、单线程、并发数控制等
代码实现
线程池接口,方便扩展
import java.util.List;
public interface ThreadPool {
void execute(Runnable task);
void execute(Runnable[] task);
void execute(List<Runnable> task);
//返回执行任务的个数
int getExecuteTaskNumber();
//返回任务队列的长度 即还没处理的任务个数
int getWaitTaskNumber();
//返回工作线程的个数
int getWorkThreadNumber();
//关闭线程池
void destory();
}
具体实现
public class ThreadPoolManager implements ThreadPool {
//线程池中默认线程的个数为5
private static int workerNum = 5;
//工作线程数组
WorkThead[] workTheads;
//执行任务数量
private static volatile int executeTaskNumber = 0;
//任务队列 作为一个缓冲 List线程不安全
private List<Runnable> taskQueue = new LinkedList<Runnable>();
//private BlockingQueue<Runnable> taskQueue = new
//ArrayBlockingQueue<Runnable>(1024);
private static ThreadPoolManager threadPool;
private AtomicLong threadNum = new AtomicLong();
private ThreadPoolManager() {
this(workerNum);
}
private ThreadPoolManager(int workerNum) {
if (workerNum > 0) {
ThreadPoolManager.workerNum = workerNum;
}
//工作线程初始化
workTheads = new WorkThead[workerNum];
for (int i = 0; i < ThreadPoolManager.workerNum; i++) {
workTheads[i]= new WorkThead();
Thread thread = new Thread(workTheads[i], "ThreadPool-worker" + threadNum.incrementAndGet());
System.out.println("初始化线程总数" + (i + 1) + "------当前线程名称是:" + thread.getName());
thread.start();
}
}
//获取线程池
public static ThreadPool getThreadPool() {
return getThreadPool(ThreadPoolManager.workerNum);
}
public static ThreadPool getThreadPool(int workerNum) {
if (workerNum <= 0) {
workerNum = ThreadPoolManager.workerNum;
}
if (threadPool == null) {
threadPool = new ThreadPoolManager(workerNum);
}
return threadPool;
}
@Override
public void execute(Runnable task) {
synchronized (taskQueue) {
taskQueue.add(task);
//通知 启动的线程
taskQueue.notifyAll();
}
}
@Override
public void execute(Runnable[] tasks) {
synchronized (taskQueue) {
for (Runnable task : tasks) {
taskQueue.add(task);
}
taskQueue.notifyAll();
}
}
@Override
public void execute(List<Runnable> tasks) {
synchronized (taskQueue) {
for (Runnable task : tasks) {
taskQueue.add(task);
}
taskQueue.notifyAll();
}
}
@Override
public int getExecuteTaskNumber() {
return executeTaskNumber;
}
@Override
public int getWaitTaskNumber() {
return taskQueue.size();
}
@Override
public int getWorkThreadNumber() {
return workerNum;
}
/**
* 线程池销毁
*/
@Override
public void destory() {
while (!taskQueue.isEmpty()) {
try {
//不断检测任务队列是否全部执行
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < workerNum; i++) {
workTheads[i].stopWorker();
workTheads[i] = null;
}
threadPool = null;
taskQueue.clear();
}
@Override
public String toString() {
return "当前工作线程数:" + workerNum +
", 已完成任务数:" + executeTaskNumber +
", 等待任务数量:" + getWaitTaskNumber();
}
private class WorkThead extends Thread {
//该工作线程是否有效 用于结束该工作线程
private boolean isRunning = true;
@Override
public void run() {
super.run();
//队列同步机制synchronized
//接收队列当中的任务对象 Runnable 类型
Runnable r = null;
//线程无效 结束run方法 线程没用了
while (isRunning) {
synchronized (taskQueue) {
//队列为空
while (isRunning && taskQueue.isEmpty()) {
try {
taskQueue.wait(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (!taskQueue.isEmpty()) {
r = taskQueue.remove(0);//取出任务
}
if (r != null) {
r.run();//执行任务
}
executeTaskNumber++;
r = null;
}
}
}
//停止工作 让该线程自然执行完run方法 自然结束
public void stopWorker() {
isRunning = false;
}
}
}
测试类
import javafx.concurrent.Task;
import java.util.ArrayList;
import java.util.List;
public class ThreadPoolTest {
public static void main(String[] args) {
ThreadPool t = ThreadPoolManager.getThreadPool(6);
List<Runnable> taskList = new ArrayList<Runnable>();
for (int i = 0; i < 100; i++) {
taskList.add(new Task());
}
t.execute(taskList);
System.out.println(t);
t.destory();//所有线程执行完才destory
System.out.println(t);
}
//任务类
static class Task implements Runnable {
private static volatile int i = 1;
@Override
public void run() {
System.out.println("当前处理的线程是:" + Thread.currentThread().getName() + " 执行任务" + (i++) + " 完成");
}
}
}
运行结果
总结
自己实现线程池,要注意线程安全、线程池销毁的合理控制,防止出现死锁等情况,当然,这只是模仿jdk线程池中的一种(FixedThreadPool 固定大小的线程池)实现,还可以模仿SingleThreadPool、CachedThreadPool、ScheduledThreadPool等jdk线程池 自行扩展