线程池分析
来源:互联网 发布:宠物翻译器软件 编辑:程序博客网 时间:2024/06/10 00:19
1,线程池
当进程中线程较少时,可以手动去新建thread。但是如果大量的线程会使进程管理很混乱,并且不断的创建销毁线程影响性能。在此情况下,线程池诞生了。线程池优点如下,
减少创建和销毁线程的次数,每个工作线程可以多次使用
可根据系统情况调整执行的线程数量,防止消耗过多内存。
2 ThreadPoolExecutor
2.1 构造方法
AsyncTask构造ThreadPoolExecutor如下,
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
1,第一个参数为int,线程池的核心线程数,核心线程会一直存活。
2,第二个参数为int,线程池最大的线程数量,超过的新线程就会被阻塞。
3,第三个参数为int,第四个参数为时间单位,单位有TimeUnit.MILLISECONDS(ms)/
TimeUnit.SECONDS(s)/TimeUnit.MINITES(分)等。表示非核心线程闲置时间超过这个时长就会被回收。
4,第五个参数表示线程池中的任务队列, AsyncTask中值为128
5,第六个参数是线程工厂,只是为线程池创建新的线程。
AsyncTask中这6个参数如下,
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); // 一般为8 private static final int CORE_POOL_SIZE = CPU_COUNT + 1; private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; private static final int KEEP_ALIVE = 1; private static final ThreadFactory sThreadFactory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); public Thread newThread(Runnable r) { return new Thread(r, "AsyncTask #" + mCount.getAndIncrement()); } }; // ThreadFactory是一个仅有newThread方法的接口 private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128);
2.1 ThreadPoolExecutor分类
Executors类中封装了几个常用的线程池,也是通过new ThreadPoolExecutor来实现的。
2.1.1 newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
newFixedThreadPool特点:
1,所有线程都是核心线程,都处于活动状态,在线程池被关闭时才回收。
2,无超时机制,任务队列无大小限制。
优点:更快响应外界的请求。
2.1.2 newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
newSingleThreadExecutor特点:
1,仅有一个核心线程。
2,无超时机制,任务队列无大小限制。
优点:所有任务都在一个线程中按照顺序执行,所以不需要处理线程同步问题。
2.1.3 newCachedThreadPool
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
newCachedThreadPool特点:
1,无核心线程,都是非核心线程。
2,超过60s的空闲线程就会被回收。
优点:适合执行大量耗时较少的任务。
2.1.4 newScheduledThreadPool
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, Integer.MAX_VALUE, DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, new DelayedWorkQueue(), threadFactory, handler);}
ScheduledThreadPoolExecutor继承于ThreadPoolExecutor
ScheduledThreadPoolExecutor特点:
1,非核心线程数无限制。
优点:适合执行定时任务和具有固定周期的重复任务。
当然还有一些其他的线程池未说明,例如ForkJoinPool
3 execute
Execute的总体调用流程图如下,
Execute方法如下,
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) reject(command); else if (workerCountOf(recheck) == 0) addWorker(null, false); } else if (!addWorker(command, false)) reject(command); }
ctl是ThreadPoolExecutor的一个重要属性,它记录着ThreadPoolExecutor的线程数量和线程状态。有32位,其中前三位用于记录线程状态,后29位用于记录线程的数量。那线程状态一共有5种状态。
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); private static final int COUNT_BITS = Integer.SIZE - 3; private static final int CAPACITY = (1 << COUNT_BITS) - 1; // runState is stored in the high-order bits private static final int RUNNING = -1 << COUNT_BITS; private static final int SHUTDOWN = 0 << COUNT_BITS; private static final int STOP = 1 << COUNT_BITS; private static final int TIDYING = 2 << COUNT_BITS; private static final int TERMINATED = 3 << COUNT_BITS;
addWorker方法如下,
private boolean addWorker(Runnable firstTask, boolean core) { // core表示是否是核心线程 retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c); // Check if queue empty only if necessary. if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; for (;;) { int wc = workerCountOf(c); if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false; if (compareAndIncrementWorkerCount(c)) break retry; c = ctl.get(); // Re-read ctl if (runStateOf(c) != rs) continue retry; // else CAS failed due to workerCount change; retry inner loop } } boolean workerStarted = false; boolean workerAdded = false; Worker w = null; try { w = new Worker(firstTask); final Thread t = w.thread; if (t != null) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { // Recheck while holding lock. // Back out on ThreadFactory failure or if // shut down before lock acquired. int rs = runStateOf(ctl.get()); if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { if (t.isAlive()) // precheck that t is startable throw new IllegalThreadStateException(); workers.add(w); int s = workers.size(); if (s > largestPoolSize) largestPoolSize = s; workerAdded = true; } } finally { mainLock.unlock(); } if (workerAdded) { t.start(); workerStarted = true; } } } finally { if (! workerStarted) addWorkerFailed(w); } return workerStarted; }
首先新建一个线程对象,然后将该对象放入workers的HashSet中,最后开始运行该线程。
private final HashSet<Worker> workers = new HashSet<Worker>();
runWorker方法如下,
final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { while (task != null || (task = getTask()) != null) { w.lock(); // If pool is stopping, ensure thread is interrupted; // if not, ensure thread is not interrupted. This // requires a recheck in second case to deal with // shutdownNow race while clearing interrupt if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt(); try { beforeExecute(wt, task); Throwable thrown = null; try { task.run(); } catch (RuntimeException x) { thrown = x; throw x; } catch (Error x) { thrown = x; throw x; } catch (Throwable x) { thrown = x; throw new Error(x); } finally { afterExecute(task, thrown); } } finally { task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { processWorkerExit(w, completedAbruptly); } }
按照顺序调用如下三个方法,
beforeExecute
task.run()
afterExecute
其中, task是回调对象,是AsyncTask中的FutureTask对象。
- Drizzle 线程池分析
- 线程池原理分析
- 线程池原理分析 .
- 线程池原理分析
- 线程池分析
- 线程池分析
- 线程池原理分析
- POCO线程池分析
- 线程池与线程队列分析-优
- 线程池(代码简单分析)
- 线程池的浅显分析
- 线程池的深入分析
- 线程池问题-例子分析
- ClamAV 0.95线程池分析
- mina框架分析:线程池
- 线程池分析与使用
- Ceph代码分析---线程池
- java 线程池 队列分析
- JavaScript显示日期与时间
- oj1995C语言实验——矩阵下三角元素之和
- Python爬虫二(Urllib库的基本使用和高级用法)
- zoj 1414 分情况讨论
- (最小生成树)HDU 1233 还是畅通工程
- 线程池分析
- C#将dll打包进exe
- 兼容不同的浏览器时间
- JDK工具类_____properties文件各种操作
- HDU 3416 最短路 + 网络流
- 安装opencv
- JAVA学习之数组操作
- leecode 解题总结:347. Top K Frequent Elements
- Android notification