线程重用——线程池的基本原理
2015-10-19 11:32
267 查看
为简单起见,线程池中只有一个线程:
ThreadFactory:
Thread.start()不能重复调用,所以要重用Thread,就不能让Thread执行完一个任务后终止,因此就必须阻塞Thread.run()方法,让该方法不停地从任务队列中获取任务并执行。
下面看看JDK的源码。
ThreadPoolExecutor.execute()方法:
这个方法启动了一个线程。
addThread():
Worker.run():
package com.xs.concurrent; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class ThreadPool { private final BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<Runnable>(); private final Thread thread; public ThreadPool() { thread = ThreadFactory.newThread(blockingQueue); thread.start(); } public void execute(Runnable runnable){ try { blockingQueue.put(runnable); } catch (InterruptedException e) { throw new RuntimeException(e); } } public static void main(String[] args) throws Exception { ThreadPool pool = new ThreadPool(); Runnable runnable = new Runnable() { @Override public void run() { System.out.println("Hello world!"); } }; for (int i = 0; i < 10; i++) { pool.execute(runnable); Thread.sleep(1000); } } }
ThreadFactory:
package com.xs.concurrent; import java.util.concurrent.BlockingQueue; public class ThreadFactory { public static Thread newThread(final BlockingQueue<Runnable> tasks){ Thread t = new Thread(new Runnable() { @Override public void run() { for (;;) { try { Runnable task = tasks.take(); // 阻塞方法,直到取到任务为止 task.run(); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }); return t; } private ThreadFactory(){} }
Thread.start()不能重复调用,所以要重用Thread,就不能让Thread执行完一个任务后终止,因此就必须阻塞Thread.run()方法,让该方法不停地从任务队列中获取任务并执行。
下面看看JDK的源码。
ThreadPoolExecutor.execute()方法:
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) { if (runState == RUNNING && workQueue.offer(command)) { if (runState != RUNNING || poolSize == 0) ensureQueuedTaskHandled(command); } else if (!addIfUnderMaximumPoolSize(command)) reject(command); // is shutdown or saturated } }addIfUnderCorePoolSize():
private boolean addIfUnderCorePoolSize(Runnable firstTask) { Thread t = null; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { if (poolSize < corePoolSize && runState == RUNNING) t = addThread(firstTask); } finally { mainLock.unlock(); } if (t == null) return false; t.start(); return true; }
这个方法启动了一个线程。
addThread():
private Thread addThread(Runnable firstTask) { Worker w = new Worker(firstTask); Thread t = threadFactory.newThread(w); if (t != null) { w.thread = t; workers.add(w); int nt = ++poolSize; if (nt > largestPoolSize) largestPoolSize = nt; } return t; }这个方法将任务交给了Worker。Worker是ThreadPoolExecutor的内部类。
Worker.run():
public void run() { try { Runnable task = firstTask; firstTask = null; while (task != null || (task = getTask()) != null) { runTask(task); // 执行任务 task = null; } } finally { workerDone(this); } }getTask()方法属于ThreadPoolExecutor类:
Runnable getTask() { for (;;) { try { int state = runState; if (state > SHUTDOWN) return null; Runnable r; if (state == SHUTDOWN) // Help drain queue r = workQueue.poll(); else if (poolSize > corePoolSize || allowCoreThreadTimeOut) r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS); else r = workQueue.take(); if (r != null) return r; if (workerCanExit()) { if (runState >= SHUTDOWN) // Wake up others interruptIdleWorkers(); return null; } // Else retry } catch (InterruptedException ie) { // On interruption, re-check runState } }该方法不停地从工作队列中获取任务。
相关文章推荐
- 异常学习笔记+打包+doc该软件包编译
- 应用系统间几种数据传输方式
- getRequestURI,getRequestURL的区别
- setTag属性
- _msdcs missing from domain's forward lookup zone
- JS数组高效率去除重复
- ApiDemos—FragmentCustomAnimations分析
- HDU2089 不要62 数位DP
- python中使用xlrd、xlwt读写excel(xls格式)
- OpenCV函数解读之groupRectangles
- ORACLE 全文索引功能实现学习笔记
- JSON
- javascript 对象的 key 都是字符串
- cocoapods安装
- MongoDB Linux下的安装和启动
- [LeetCode]Number of 1 Bits
- 基于Qt有限状态机的一种实现方式和完善的人工智能方法
- js 日期相减得到天数
- iOS 约束 自动布局 UI
- Linux make学习