目录
线程池,除了池的功能外,还提供了更全面的线程管理、任务提交等方法。
juc的executors目前提供了5种不同的线程池创建配置
它会试图缓存线程并重用,当无缓存线程可用时,就会创建新的工作线程。工作线程的创建数量有限制为interger. max_value。
其内部使用synchronousqueue作为工作队列
executor是一个基础的接口,其初衷是将任务提交和任务执行细节解耦,使开发者不被太多线程创建、调度等不相关细节所打扰。
void execute(runnable command);
executorservice则更加完善,不仅提供service的管理功能,比如shutdown等方法,也提供了更加全面的提交任务机制,如返回future而不是void的submit方法。
<t> future<t> submit(callable<t> task);
private fnal blockingqueue<runnable> workqueue;
private fnal hashset<worker> workers = new hashset<>();
public threadpoolexecutor(int corepoolsize, int maximumpoolsize, long keepalivetime, timeunit unit, blockingqueue<runnable> workqueue, threadfactory threadfactory, rejectedexecutionhandler handler)
private fnal atomicinteger ctl = new atomicinteger(ctlof(running, 0)); // 真正决定了工作线程数的理论上限 private static fnal int count_bits = integer.size - 3; private static fnal int count_mask = (1 << count_bits) - 1; // 线程池状态,存储在数字的高位 private static fnal int running = -1 << count_bits; … // packing and unpacking ctl private static int runstateof(int c) { return c & ~count_mask; } private static int workercountof(int c) { return c & count_mask; } private static int ctlof(int rs, int wc) { return rs | wc; }
public void execute(runnable command) { … int c = ctl.get(); // 检查工作线程数目,低于corepoolsize则添加worker if (workercountof(c) < corepoolsize) { if (addworker(command, true)) return; c = ctl.get(); } // isrunning就是检查线程池是否被shutdown // 工作队列可能是有界的,ofer是比较友好的入队方式 if (isrunning(c) && workqueue.ofer(command)) { int recheck = ctl.get(); // 再次进行防御性检查 if (! isrunning(recheck) && remove(command)) reject(command); else if (workercountof(recheck) == 0) addworker(null, false); } // 尝试添加一个worker,如果失败以为着已经饱和或者被shutdown了 else if (!addworker(command, false)) reject(command); }
如果我们的任务主要是进行计算,通常建议按照cpu核的数目n或者n+1。
如果是需要较多等待的任务,例如i/o操作比较多,可以参考brain goetz推荐的计算方法:线程数 = cpu核数 × (1 + 平均等待时间/平均工作时间)
要注意:
《java并发实战》
《java核心技术36讲》杨晓峰
如对本文有疑问, 点击进行留言回复!!
Android 4.0使用Kotlin调用C语言以及汇编语言
Java Class.forName()用法和newInstance()方法原理解析
网友评论