线程池ExecutorService 中并发数的(引入信号量Semaphore)控制执行
2017-11-27 22:13
585 查看
查看本机处理器的核心数代码:Runtime.getRuntime().availableProcessors()
所以,应用程序的最小线程数应该等于可用的处理器核数。如果所有的任务都是计算密集型的,则创建处理器可用的核心数那么多线程就可以了。在这种情况下,创建更多的线程对程序性能而言反而是不利的。因为当有多个任务处于就绪状态时,处理器核心需要在线程间频繁进行上下文切换,而这种切换对程序性能损耗较大。但如果任务都是IO密集型的,那么我们就需要开更多的线程来提高性能。
当一个任务执行IO操作时,其线程将被阻塞,于是处理器可以立即进行上下文的切换以便处理其他就绪线程。如果我们只有处理可用核心数那么多个线程的话,则即使有待执行的任务也无法处理,因为我们已经拿不出更多的线程供处理器调度了。
如果任务有50%的时间处于阻塞状态,则程序所需线程数为处理器可用核心数的两倍。如果任务被阻塞的时间少于50%,即这些任务是计算密集型的,则程序所需线程数将随之减少,但最少也不应低于处理器的核心数。如果任务被阻塞的时间大于执行时间,即该任务是IO密集型的,我们就需要创建比处理器核心数大几倍数量的线程。
线程数=CPU可用核心数/(1-阻塞系数),其中阻塞系数取值0和1之间。
计算密集型任务阻塞系数为0,而IO密集型任务的阻塞系数接近1。
废话,不多说了哈!直接上代码:
所以,应用程序的最小线程数应该等于可用的处理器核数。如果所有的任务都是计算密集型的,则创建处理器可用的核心数那么多线程就可以了。在这种情况下,创建更多的线程对程序性能而言反而是不利的。因为当有多个任务处于就绪状态时,处理器核心需要在线程间频繁进行上下文切换,而这种切换对程序性能损耗较大。但如果任务都是IO密集型的,那么我们就需要开更多的线程来提高性能。
当一个任务执行IO操作时,其线程将被阻塞,于是处理器可以立即进行上下文的切换以便处理其他就绪线程。如果我们只有处理可用核心数那么多个线程的话,则即使有待执行的任务也无法处理,因为我们已经拿不出更多的线程供处理器调度了。
如果任务有50%的时间处于阻塞状态,则程序所需线程数为处理器可用核心数的两倍。如果任务被阻塞的时间少于50%,即这些任务是计算密集型的,则程序所需线程数将随之减少,但最少也不应低于处理器的核心数。如果任务被阻塞的时间大于执行时间,即该任务是IO密集型的,我们就需要创建比处理器核心数大几倍数量的线程。
线程数=CPU可用核心数/(1-阻塞系数),其中阻塞系数取值0和1之间。
计算密集型任务阻塞系数为0,而IO密集型任务的阻塞系数接近1。
废话,不多说了哈!直接上代码:
package zl; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * Semaphore还提供一些其他方法: int availablePermits() :返回此信号量中当前可用的许可证数。 int getQueueLength():返回正在等待获取许可证的线程数。 boolean hasQueuedThreads() :是否有线程正在等待获取许可证。 void reducePermits(int reduction) :减少reduction个许可证。是个protected方法。 Collection getQueuedThreads() :返回所有等待获取许可证的线程集合。是个protected方法。 tryAcquire()方法尝试获取许可证 * @author ZL * 2017年11月26日 */ public class SemaphoreTest { private static final int THREAD_COUNT = 30;//总共的线程数 private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT); private static Semaphore semaphore = new Semaphore(10);//可以并发执行的线程数 public static void main(String[] args) { for (int i = 0; i < THREAD_COUNT; i++) { final int j=i; threadPool.execute(new Runnable() { public void run() { try { semaphore.acquire();//acquire()获取一个许可证 /** * 要执行的代码块 */ System.out.println(j+"zl"); semaphore.release();//使用完之后调用release()归还许可证 } catch (InterruptedException e) { } } }); } threadPool.shutdown(); } }
相关文章推荐
- Executor框架是指java 5中引入的一系列并发库中与executor相关的一些功能类,其中包括线程池,Executor,Executors,ExecutorService,Completion
- Java Executor并发框架(九)Executor框架线程池ExecutorService.shutdown什么时候执行
- 利用GCD信号量(dispatch_semaphore)控制并发
- iOS控制高并发-dispatch_semaphore(信号量)的用法
- GCD 信号量控制并发 (dispatch_semaphore)
- 多线程线程池控制一个方法的并发量 限制只有5个线程执行任务
- C# 执行固定个数任务自行控制进入线程池的线程数量,多任务同时但是并发数据限定
- Java并发专题 带返回结果的批量任务执行 CompletionService ExecutorService.invokeAll
- GCD 信号量控制并发 (dispatch_semaphore)
- Java并发专题 带返回结果的批量任务执行 CompletionService ExecutorService.invokeAll
- 多线程和并发中新的任务执行架构Executor、ExecutorService、ScheduledExecutorService
- Java Executor并发框架(七)Executor框架线程池任务执行全过程(下)
- PAIP.并发编程 多核编程 线程池 ExecutorService的判断线程结束
- 9.JDK并发包-同步控制之信号量(Semaphore)
- GCD 信号量控制并发(dispatch_semaphore)以及dispatch_group_async
- PAIP.并发编程 多核编程 线程池 ExecutorService的判断线程结束
- GCD 信号量控制并发 (dispatch_semaphore)
- java利用线程池(ExecutorService)配合Callable和Future实现执行方法超时的阻断
- Java并发专题 带返回结果的批量任务执行 CompletionService ExecutorService.invokeAll
- Java并发专题 带返回结果的批量任务执行 CompletionService ExecutorService.invokeAll(转)