tryLock方法:
线程在调用lock方法来获得另一个线程所持有的锁的时候,很可能发生阻塞。应该更加谨慎的申请锁。
tryLock方法试图申请一个锁,成功返回true,否则返回false。
tryLock可以带有超时参数,例如:
lock.tryLock(100,TimeUnit.MILLISECONDS);
第一个参数是数值,第二个参数是单位。
如果调用带有超时参数的tryLock,那么如果线程在等待期间被中断,将抛出InterruptedException异常,这代表着允许程序打破死锁。
也可以调用lockInterruptibly方法,相当于超时为无限的tryLock方法。
条件对象进行等待时,也可以提供一个超时。
读写锁:
ReentrantReadWriteLock
读写锁允许同时有很多线程读取但仍然只能有一个线程修改。
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private Lock readLock = lock.readLock();
private Lock writedLock = lock.writeLock();
readLock.lock();
writedLock.lock();
为什么弃用stop和suspend?
试图控制一个线程的行为很可能会导致在代码执行到某一个位置时被终止从而导致对象的破坏。
阻塞队列:
对于许多线程问题,可以使用一个或多个队列将其形式化:生产者线程向队列插入元素,消费者线程则取出他们。
当试图向队列添加元素而队列已满,或是想从队列移除元素而队列为空的时候,阻塞队列导致线程阻塞。
在协调多个线程之间的合作时,阻塞队列是一个很有用的工具。工作者线程可以周期性的将中间结果存储在阻塞队列中,其他工作者线程移除中间结果并进一步加以修改。
PriorityBlockingQueue是一个带优先级的队列
LinkedBlockingDeque是一个双端队列
ArrayBlockingQueue在构造时需要指定容量
DelayQueue包含实现Delayed接口的对象,元素只有在延迟用完才能从队列中移除
interface Delayed extends Comparable<Delayed>
{
long getDelay(TimeUnit unit);
}
线程安全的集合:
java.util.concurrent提供了映像,有序集和队列的高效实现:
ConcurrentHashMap,ConcurrentSkipListMap,ConcurrentLinkedQueue
这些集合允许并发地访问数据结构的不同部分来实竞争极小化。
集合的size方法通常需要遍历数据。
集合返回弱一致性的迭代器。这意味着迭代器不一定能反映出它们被构造之后所有的修改,但是他们不会将同一个值返回两次,也不会抛出ConcurrentModificationException异常。
同步包装器:
List<E> synchArrayList = Collections.sychronizedList(new ArrayList<E>());
任何集合类通过同步包装器变成线程安全的。
但是,这些集合在迭代时依然可能会遇到一些问题。