说明
手写的一个简单的线程池,旨在帮助了解线程池的工作原理。
核心内容
- 核心工作线程
- 任务阻塞队列
定义一个内部类去实现核心工作线程
/**
* 内部类:工作的核心线程
*/
private final class WorkerThread extends Thread {
String name;
//构造方法
WorkerThread(String name) {
this.name = name;
}
@Override
public void run() {
while (!getPoolState()) {
try {
Runnable task = taskQueue.take();
if (task != null) {
getThreadLog("任务开始执行:" + task.toString());
task.run();
}
//释放内存
task = null;
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("线程关闭");
}
}
使用一个阻塞队列存放需要处理的任务列表
//存放任务执行结束的队列
private volatile BlockingQueue<Runnable> taskQueue;
//记录线程池中线程的个数
private final Set<WorkerThread> workerThreadSet = new HashSet<>();
完整测试代码
package com.leo.demo.threadtest.mythreadpool;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
/**
* @ClassName: MyThreadPool
* @Description: 小的线程池模型
* 1、线程池的
* @Author: leo825
* @Date: 2020-05-11 23:08
* @Version: 1.0
*/
public class MyThreadPool {
//核心线程数
private int corePoolSize;
//最大线程数
private int maximumPoolSize;
//存放任务执行结束的队列
private volatile BlockingQueue<Runnable> taskQueue;
//记录线程池中线程的个数
private final Set<WorkerThread> workerThreadSet = new HashSet<>();
//当前存放当前线程数
private int workerCount = 0;
//线程池关闭状态
private volatile boolean THREADPOOL_SHUTDOWN = false;
/**
* 线程池构造方法,先不考虑参数校验问题
*
* @param corePoolSize
* @param maximumPoolSize
* @param taskQueue
*/
MyThreadPool(int corePoolSize, int maximumPoolSize, BlockingQueue<Runnable> taskQueue) {
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.taskQueue = taskQueue;
//构造线程池中的线程
for (int i = 0; i < corePoolSize; i++) {
WorkerThread workerThread = new WorkerThread("poolThread_" + i);
workerThread.start();
workerThreadSet.add(workerThread);
workerCount++;
}
}
/**
* 向线程池中提交任务执行结束
*
* @param task
*/
public void submit(Runnable task) {
if (taskQueue.offer(task)) {
getThreadLog("任务执行结束添加成功: " + task.toString());
} else {
getThreadLog("任务执行结束添加失败: " + task.toString());
}
}
/**
* 关闭线程池
*/
public void shutdown() {
getThreadLog("关闭线程池");
THREADPOOL_SHUTDOWN = true;
}
/**
* 内部类:工作的核心线程
*/
private final class WorkerThread extends Thread {
String name;
//构造方法
WorkerThread(String name) {
this.name = name;
}
@Override
public void run() {
while (!THREADPOOL_SHUTDOWN) {
try {
Runnable task = taskQueue.take();
if (task != null) {
getThreadLog("任务开始执行:" + task.toString());
task.run();
}
//释放内存
task = null;
} catch (Exception e) {
e.printStackTrace();
}
}
getThreadLog("线程关闭");
}
}
/**
* 获取线程名和时间
*
* @return
*/
public static void getThreadLog(String logContent) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("[");
stringBuffer.append(Thread.currentThread().getName());
stringBuffer.append(" ");
stringBuffer.append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
stringBuffer.append("] ");
stringBuffer.append(logContent);
System.out.println(stringBuffer.toString());
}
/**
* 测试main方法
*
* @param args
*/
public static void main(String[] args) throws InterruptedException {
//定义一个阻塞队列存放任务
BlockingQueue<Runnable> workQueue = new LinkedBlockingDeque<>(5);
//构造自己的线程池
MyThreadPool threadPool = new MyThreadPool(3, 5, workQueue);
//任务执行结束数量
int size = 15;
for (int i = 0; i < size; i++) {
threadPool.submit(new Runnable() {
@Override
public void run() {
try {
int times = ThreadLocalRandom.current().nextInt(2, 6);
TimeUnit.SECONDS.sleep(times);
getThreadLog("任务执行结束 " + this.toString() + ",执行时长:" + times + " 秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
//休息20秒
TimeUnit.SECONDS.sleep(20);
//关闭线程池,此处不管用的,待后续分析源码
threadPool.shutdown();
}
}
测试结果如下:
[Thread-0 2020-06-09 11:32:12.698] 任务开始执行:com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@3fee733d
[main 2020-06-09 11:32:12.696] 任务执行结束添加成功: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@3fee733d
[main 2020-06-09 11:32:12.699] 任务执行结束添加成功: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@2a84aee7
[main 2020-06-09 11:32:12.699] 任务执行结束添加成功: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@a09ee92
[main 2020-06-09 11:32:12.699] 任务执行结束添加成功: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@30f39991
[main 2020-06-09 11:32:12.700] 任务执行结束添加成功: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@452b3a41
[main 2020-06-09 11:32:12.700] 任务执行结束添加成功: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@4a574795
[main 2020-06-09 11:32:12.700] 任务执行结束添加失败: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@f6f4d33
[main 2020-06-09 11:32:12.701] 任务执行结束添加失败: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@23fc625e
[main 2020-06-09 11:32:12.701] 任务执行结束添加失败: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@3f99bd52
[main 2020-06-09 11:32:12.701] 任务执行结束添加失败: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@4f023edb
[main 2020-06-09 11:32:12.702] 任务执行结束添加失败: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@3a71f4dd
[main 2020-06-09 11:32:12.703] 任务执行结束添加失败: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@7adf9f5f
[main 2020-06-09 11:32:12.703] 任务执行结束添加失败: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@85ede7b
[main 2020-06-09 11:32:12.703] 任务执行结束添加失败: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@5674cd4d
[main 2020-06-09 11:32:12.704] 任务执行结束添加失败: com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@63961c42
[Thread-1 2020-06-09 11:32:12.709] 任务开始执行:com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@2a84aee7
[Thread-2 2020-06-09 11:32:12.711] 任务开始执行:com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@a09ee92
[Thread-0 2020-06-09 11:32:14.712] 任务执行结束 com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@3fee733d,执行时长:2 秒
[Thread-0 2020-06-09 11:32:14.714] 任务开始执行:com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@30f39991
[Thread-1 2020-06-09 11:32:16.710] 任务执行结束 com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@2a84aee7,执行时长:4 秒
[Thread-1 2020-06-09 11:32:16.711] 任务开始执行:com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@452b3a41
[Thread-2 2020-06-09 11:32:17.712] 任务执行结束 com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@a09ee92,执行时长:5 秒
[Thread-2 2020-06-09 11:32:17.712] 任务开始执行:com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@4a574795
[Thread-0 2020-06-09 11:32:17.715] 任务执行结束 com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@30f39991,执行时长:3 秒
[Thread-1 2020-06-09 11:32:19.711] 任务执行结束 com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@452b3a41,执行时长:3 秒
[Thread-2 2020-06-09 11:32:21.713] 任务执行结束 com.leo.demo.threadtest.mythreadpool.MyThreadPool$1@4a574795,执行时长:4 秒
[main 2020-06-09 11:32:32.704] 关闭线程池
问题和思考
以上就是一个很小的线程池的模型,这个模型还存在很多问题。
- 线程池的最大线程数是核心线程满、阻塞队列满之后线程池扩展到最大线程数,线程池扩容是如何实现的?
- 线程空闲后是如何进行销毁的?
- 线程池相关的监控指标,历史最大线程数、当前线程数、累计执行任务数?
- 线程池是如何销毁的?
- 如果taskQueue队列满了,如何管理容量?
- 如果taskQueue中没有任务了,线程池活跃线程数如何看?
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/72708.html