自己动手,写一个简单的线程池(2)
来源:互联网 发布:jquery 1.11.0.min.js 编辑:程序博客网 时间:2024/05/21 19:23
上一篇中简单实现了一个线程池,但是还有问题没有解决
1.没有任务加入策略。即可以无限多向任务队列中添加任务
2.没有关闭线程池
因此对其进行改造
任务加入策略
首先定义策略接口及异常
@FunctionalInterfacepublic interface DiscardPolicy { void discard() throws DiscardException;}
public class DiscardException extends Exception { public DiscardException(String message) { super(message); }}
在SimpleThreadPool
中定义任务队列的大小 private static final int TASK_QUEUE_DEFAULT_SIZE = 20;
和策略 private final DiscardPolicy discardPolicy;
修改构造方法
public SimpleThreadPool() { this(DEFAULT_SIZE, TASK_QUEUE_DEFAULT_SIZE, DEFAULT_POLICY); } public SimpleThreadPool(int size, int taskSize, DiscardPolicy discardPolicy) { this.size = size; this.TASK_SIZE = taskSize; this.discardPolicy = discardPolicy; init(); }
加入任务时做校验
public void addTask(Runnable runnable) throws Exception { synchronized (TASK_QUEUE) { } if (TASK_QUEUE.size() >= TASK_SIZE) { discardPolicy.discard(); } TASK_QUEUE.addLast(runnable); TASK_QUEUE.notifyAll(); } }
如果大小超过限制,则由策略处理。
这里设置一个默认的策略,即抛出异常
public static final DiscardPolicy DEFAULT_POLICY = () -> { throw new DiscardException("task size too large."); };
测试
public class SimpleThreadPoolTest { public static void main(String[] args) throws Exception { SimpleThreadPool pool = new SimpleThreadPool(); for (int i = 0; i < 40; i++) { int finalI = i; pool.addTask(() -> { System.out.println(Thread.currentThread().getName() + " ==> is execute task " + finalI); try { Thread.sleep(2_000); } catch (InterruptedException e) { e.printStackTrace(); } }); } }}
抛出异常
Exception in thread "main" com.ran.learn.lession2.DiscardException: task size too large. at com.ran.learn.lession2.SimpleThreadPool.lambda$static$0(SimpleThreadPool.java:25) at com.ran.learn.lession2.SimpleThreadPool.addTask(SimpleThreadPool.java:56) at com.ran.learn.lession2.SimpleThreadPoolTest.main(SimpleThreadPoolTest.java:11) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)SIMPLE_THREAD_POOL-9 ==> is execute task 0SIMPLE_THREAD_POOL-3 ==> is execute task 6SIMPLE_THREAD_POOL-2 ==> is execute task 7SIMPLE_THREAD_POOL-4 ==> is execute task 5...
关闭线程池
定义shutdown
方法
public void shutdown() { while (!TASK_QUEUE.isEmpty()) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } int executors = TASK_EXECUTORS.size(); while (executors > 0) { for (TaskExecutor taskExecutor : TASK_EXECUTORS) { if (taskExecutor.getTaskState() == TaskState.BLOCKED) { taskExecutor.interrupt(); taskExecutor.shutdown(); executors--; } else { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } } System.out.println("all threads are dead."); isShutDown = true; }
首先判断任务队列是否为空,如果不为空,肯定无法关闭。当任务队列为空时,还需要判断每个执行线程的状态,因为任务可能被分配的到不同的线程中执行,当执行完毕时,则让其生命周期结束。线程池就被关闭了。
定义变量标记是否被shutdown,如果被shutdown,不接受新加入的任务。 private static boolean isShutDown = false;
public void addTask(Runnable runnable) throws Exception { synchronized (TASK_QUEUE) { if (isShutDown) { throw new Exception("thread poll is shutdown."); } if (TASK_QUEUE.size() >= TASK_SIZE) { discardPolicy.discard(); } TASK_QUEUE.addLast(runnable); TASK_QUEUE.notifyAll(); } }
测试
public class SimpleThreadPoolTest { public static void main(String[] args) throws Exception { SimpleThreadPool pool = new SimpleThreadPool(); for (int i = 0; i < 20; i++) { int finalI = i; pool.addTask(() -> { System.out.println(Thread.currentThread().getName() + " ==> is execute task " + finalI); try { Thread.sleep(2_000); } catch (InterruptedException e) { e.printStackTrace(); } }); } pool.shutdown(); }}
输出
SIMPLE_THREAD_POOL-5 ==> is execute task 4SIMPLE_THREAD_POOL-0 ==> is execute task 9SIMPLE_THREAD_POOL-1 ==> is execute task 8SIMPLE_THREAD_POOL-2 ==> is execute task 7SIMPLE_THREAD_POOL-3 ==> is execute task 6SIMPLE_THREAD_POOL-8 ==> is execute task 1SIMPLE_THREAD_POOL-6 ==> is execute task 3SIMPLE_THREAD_POOL-9 ==> is execute task 0SIMPLE_THREAD_POOL-7 ==> is execute task 2SIMPLE_THREAD_POOL-4 ==> is execute task 5SIMPLE_THREAD_POOL-5 ==> is execute task 11SIMPLE_THREAD_POOL-1 ==> is execute task 12SIMPLE_THREAD_POOL-4 ==> is execute task 19SIMPLE_THREAD_POOL-8 ==> is execute task 15SIMPLE_THREAD_POOL-3 ==> is execute task 14SIMPLE_THREAD_POOL-9 ==> is execute task 17SIMPLE_THREAD_POOL-6 ==> is execute task 16SIMPLE_THREAD_POOL-0 ==> is execute task 10SIMPLE_THREAD_POOL-7 ==> is execute task 18SIMPLE_THREAD_POOL-2 ==> is execute task 13all threads are dead.
执行完成后退出
完整代码
public class SimpleThreadPool { private final int size; private final static int DEFAULT_SIZE = 10; private static final LinkedList<Runnable> TASK_QUEUE = new LinkedList<>(); private static final String THREAD_PREFIX = "SIMPLE_THREAD_POOL-"; private static volatile int seq = 0; private static final List<TaskExecutor> TASK_EXECUTORS = new ArrayList<>(); private static final ThreadGroup THREAD_GROUP = new ThreadGroup("Simple_Threadpool_group"); private static int TASK_SIZE; private static final int TASK_QUEUE_DEFAULT_SIZE = 20; private static boolean isShutDown = false; public static final DiscardPolicy DEFAULT_POLICY = () -> { throw new DiscardException("task size too large."); }; private final DiscardPolicy discardPolicy; public SimpleThreadPool() { this(DEFAULT_SIZE, TASK_QUEUE_DEFAULT_SIZE, DEFAULT_POLICY); } public SimpleThreadPool(int size, int taskSize, DiscardPolicy discardPolicy) { this.size = size; this.TASK_SIZE = taskSize; this.discardPolicy = discardPolicy; init(); } private void init() { for (int i = 0; i < size; i++) { TaskExecutor taskExecutor = createExecutor(); TASK_EXECUTORS.add(taskExecutor); taskExecutor.start(); } } public void addTask(Runnable runnable) throws Exception { synchronized (TASK_QUEUE) { if (isShutDown) { throw new Exception("thread poll is shutdown."); } if (TASK_QUEUE.size() >= TASK_SIZE) { discardPolicy.discard(); } TASK_QUEUE.addLast(runnable); TASK_QUEUE.notifyAll(); } } public void shutdown() { while (!TASK_QUEUE.isEmpty()) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } int executors = TASK_EXECUTORS.size(); while (executors > 0) { for (TaskExecutor taskExecutor : TASK_EXECUTORS) { if (taskExecutor.getTaskState() == TaskState.BLOCKED) { taskExecutor.interrupt(); taskExecutor.shutdown(); executors--; } else { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } } System.out.println("all threads are dead."); isShutDown = true; } private TaskExecutor createExecutor() { TaskExecutor executor = new TaskExecutor(THREAD_GROUP, THREAD_PREFIX + (seq++)); return executor; } enum TaskState { FREE, RUNNING, BLOCKED, DEAD } private static class TaskExecutor extends Thread { private TaskState taskState = TaskState.FREE; private TaskExecutor(ThreadGroup threadGroup, String name) { super(threadGroup, name); } public TaskState getTaskState() { return taskState; } public void run() { OUTER: while (taskState != TaskState.DEAD) { Runnable runnable; synchronized (TASK_QUEUE) { while (TASK_QUEUE.isEmpty()) { try { taskState = TaskState.BLOCKED; TASK_QUEUE.wait(); } catch (InterruptedException e) { break OUTER; } } runnable = TASK_QUEUE.removeFirst(); } taskState = TaskState.RUNNING; runnable.run(); taskState = TaskState.FREE; } } public void shutdown() { taskState = TaskState.DEAD; } }}
@FunctionalInterfacepublic interface DiscardPolicy { void discard() throws DiscardException;}
public class DiscardException extends Exception { public DiscardException(String message) { super(message); }}
public class SimpleThreadPoolTest { public static void main(String[] args) throws Exception { SimpleThreadPool pool = new SimpleThreadPool(); for (int i = 0; i < 20; i++) { int finalI = i; pool.addTask(() -> { System.out.println(Thread.currentThread().getName() + " ==> is execute task " + finalI); try { Thread.sleep(2_000); } catch (InterruptedException e) { e.printStackTrace(); } }); } pool.shutdown(); pool.addTask(() -> System.out.println("===")); }}
阅读全文
0 0
- 自己动手,写一个简单的线程池(2)
- 自己动手,写一个简单的线程池(1)
- 自己动手,写一个简单的线程池(3)
- 自己动手写一个简单的MVC框架(第一版)
- 自己动手写一个简单的MVC框架(第二版)
- 自己动手写一个简单的MVC框架(第二版)
- 自己动手写一个简单的bootloader
- 写一个简单的线程池
- 自己动手实现简单的线程池
- 自己动手写一个简单的Shell之一:了解Shell
- 自己动手写一个简单的Shell之二:运行程序
- 自己动手写一个简单的Shell之三:命令行解析
- 自己动手写一个简单的Shell之四:流程控制
- 自己动手写一个简单的Windows shell扩展程序
- 自己动手写一个简单的php模板引擎
- 自己动手写一个简单图片轮播的控件
- 自己动手写简单的eventbus
- ROS(二)自己动手写一个简单的发布(Publisher)、订阅(Subscriber)程序
- Hibernate事务传播行为种类
- JZOJ5431. 【NOIP2017提高A组集训10.28】序列操作
- IO流学习总结
- OpenCV学习笔记(31)练习 xml文件读取
- 高并发服务设计—缓存
- 自己动手,写一个简单的线程池(2)
- Java
- 10-30上午测试(DAY 2 R1)
- 将某个照片文件加入系统共享文件
- k8s 学习笔记
- 机器学习算法优缺点及其应用领域
- RxJava2系列之背压策略(一)
- Ubuntu16安装mysql、mongodb、redis、apache
- keepalived