The Art of Java Concurrency Programming IV
文章目录
第八章、Java中的并发工具类
8.1、CountDownLatch
- 多线程的计数器,控制并发
8.2、CyclicBarrier
- 构造屏障,直到最后一个线程到达后才执行所有线程
- 高级的构造函数CyclicBarrier(int, Runnable),线程到达屏障后,优先执行Runnable
- reset方法可以重置,而CountDownLatch无法重置,只可使用一次
8.3、控制并发线程数的Semaphore
- 控制线程的并发数
8.4、线程交换数据Exchanger
- 第一个线程执行Exchange方法,其会等待第二个线程执行Exchange
- 可用于遗传算法
第九章、Java线程池
9.1、Java线程池模型
- 关于全局锁,见源码mainLock,用于锁存放线程Worker(对于用户线程的再次封装)的HashSet
9.2、线程池的使用
1、参数部分
123456789101112131415161718192021222324252627282930/*** Creates a new {@code ThreadPoolExecutor} with the given initial* parameters.** @param corePoolSize 基本的核心线程数,如果调用prestartAllCoreThreads则线程池会提前创建并启动所有基本线程* @param maximumPoolSize 线程池最大数量,如果BlockingQueue无穷大则无效果(Thread只会不断进入Queue中)* @param keepAliveTime 核心线程之外的线程空闲时候的保持时间,任务很多而执行较快可以调大;默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0* @param unit keepAliveTime的时间单位* @param workQueue 用于保存等待执行任务的阻塞队列* @param threadFactory 创建线程的工厂,可以通过其给每个创建出来的线程设置有意义的名字,guava可以快速的配置这类线程工厂(new ThreadFactoryBuilder().setNameFormat("XX-task-%d").build())* @param handler 饱和策略,当队列和线程池都满时,执行,默认有四种* ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。* ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。* ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)* ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务* @throws IllegalArgumentException if one of the following holds:<br>* {@code corePoolSize < 0}<br>* {@code keepAliveTime < 0}<br>* {@code maximumPoolSize <= 0}<br>* {@code maximumPoolSize < corePoolSize}* @throws NullPointerException if {@code workQueue}* or {@code threadFactory} or {@code handler} is null*/public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
2、提交任务
- submit提交有返回值的任务,相反用execute
3、线程池的关闭
- shutdownNow:首先将线程池状态变为STOP,尝试所有正在执行或暂停的任务,返回等待的任务列表(BQueue中的),如果任务不一定要执行完,则使用这种
- shutdown:将状态设置为SHUTDOWN,之后中断所有没有正在执行的任务,一般使用shutdown
4、合理的配置线程池
- CPU密集型任务应配置尽可能小的线程,IO密集型任务由于并不是一直在执行任务,则应配置尽可能多的线程,如2*CPU_NUM
- 混合型任务可以考虑拆分为一个CPU型与IO型
- 优先级不同的任务考虑使用优先级队列,但是会出现饥饿问题
- 依赖数据库连接池的任务,应该设置线程数较大,更好的使用CPU
- 使用有界队列,增强预警能力