为什么要线程池?
简单来说使用线程池有以下几个目的:
线程是稀缺资源,不能频繁的创建。
解耦作用;线程的创建于执行完全分开,方便维护。
应当将其放入一个池子中,可以给其他任务进行复用。
线程池的实现原理
任务提交,执行execute方法后,检查当前运行的线程数据量是否达到核心线程池的大小,如果未达到,则创建新的线程去处理任务,否则进行第2步
核心线程池满了后,任务将放置在同步队列中,等待核心线程的处理,即第4步。如果同步队列中存储的任务已经满了,将进行第3步
同步队列满了后,则创建新的线程来处理任务,直到线程数量达到最大线程数量时,则进行第5步
核心线程反复的从同步队列中拉取任务处理
当前运行的线程数超过maximumPoolSize,任务将被拒绝,并执行拒绝策略(RejectedExecutionHandler)
实现一个简单的线程池:
代码演示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| class MyExecutor implements Executor { private static final int DEFAULT_SIZE = 10; private static final int DEFAULT_CAPACITY = 16; private ArrayBlockingQueue<Runnable> queue; private int size;
public MyExecutor() { this.size = DEFAULT_SIZE; queue = new ArrayBlockingQueue<>(DEFAULT_CAPACITY); init(); }
public MyExecutor(int size, int capacity) { if(size <= 0 || capacity <= 0) throw new IllegalArgumentException("size =" + size + ",capacity =" + capacity); this.size = size; queue = new ArrayBlockingQueue<>(capacity); init(); }
private void init() { for (int i = 0; i < size; i++) { new workThread().start(); } } @Override public void execute(Runnable command) { try { queue.put(command); } catch (InterruptedException e) { e.printStackTrace(); } }
private class workThread extends Thread { @Override public void run() { while(true) { Runnable task = null; try { task = queue.take(); } catch (InterruptedException e) { e.printStackTrace(); } task.run(); } } } }
public class MyExecutorTest { public static void main(String[] args) { Executor exec = new MyExecutor();
for (int i = 0; i < 5; i++) { exec.execute(new RunnableImpl(i)); } } }
|
结果演示:
1 2 3 4 5 6 7 8 9 10
| Thread-0创建了一个新的线程,开始执行任务0 Thread-2创建了一个新的线程,开始执行任务3 Thread-5创建了一个新的线程,开始执行任务1 Thread-3创建了一个新的线程,开始执行任务2 Thread-4创建了一个新的线程,开始执行任务4 Thread-3创建了一个新的线程,执行完毕2 Thread-2创建了一个新的线程,执行完毕3 Thread-4创建了一个新的线程,执行完毕4 Thread-5创建了一个新的线程,执行完毕1 Thread-0创建了一个新的线程,执行完毕0
|
线程池-API
参考文档
---------------- The End ----------------