死锁
某个任务在等待另一个任务,而后者又等待别的任务,这样一直下去,直到这个链条上的任务又在等待第一个任务释放锁。这得到了一个任务之间相互等待的连续循环,没有哪个线程能继续,这被称之为死锁。
新类库中的构件
CountDownLatch
它被用来同步一个或多个任务,强制它们等待由其他任务执行的一组操作完成。
CyclicBarrier
CyclicBarrier适用于这样的情况:你希望创建一组任务,它们并行地执行工作,然后在进行下一步骤之前等待,直至所有任务都完成(看起来像jion())。它使得所有的并行任务都将在栅栏处队列,因此可以一致地向前移动。这非常像CountDownLatch,只是CountDownLatch事只触发一次的事件,而CyclicBarrier可以多次重用。
DelayQueue
这是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。这种队列是有序的,即队头对象的延迟到期的时间最长。如果没有任何延迟到期,那么就不会有任何头元素,平切poll()将返回null(正因为这样,你不能讲null放置到这种队列中)
PriorityBlockingQueue
这是一个很基础的优先级队列,它具有可阻塞的读取操作。下面是一个示例,其中在优先级队列中的对象是按照优先级顺序从队列中出现的任务。
使用ScheduledExecutor的温室控制器
Semaphore
正常的锁(来自concurrent.locks或内建的synchronized锁)在任何时刻都只允许一个任务访问一项资源,而计数信号量允许n个任务同时访问这个资源。
Exchanger
仿真
-银行出纳员仿真
-饭店仿真
-分发工作
性能调优
-比较各类互斥计数
-乐观锁
-比较各种Map实现
-乐观加锁
总结:
多线程的基础总结
1、可以运行多个独立的任务
2、必须考虑当这些任务关闭时,可能出现的所有问题
3、任务可能会在共享资源上彼此干涉。互斥(锁)是用来防止这种冲突的基本工具。
4、如果任务设计得不够仔细,就有可能会死锁
明白什么时候应该使用并发、什么时候应该避免使用并发是非常关键的。使用它的原因主要是:
1、要处理很多任务,它们交织在一起,应用并发能够更有效的使用计算机(包括在多个CPU上透明地分配任务的能力)
2、要能够更好地组织代码
3、要更便于用户使用
多线程的主要缺陷有:
1、等待共享资源的时候性能降低
2、需要处理线程的额外CPU花费
3、糟糕的程序设计导致不必要的复杂度
4、有可能产生一些病态行为,如饿死,竞争,死锁和活锁(多个运行各自任务的线程使得整体无法完成)
5、不同平台导致的不一致性。