》线程的优先级
线程的优先级是高度依赖于操作系统的,Windows NT/XP有7个优先级别。JAVA的某些优先级将会映射到相同的操作系统的优先级上。在SUN为Linux提供的Java虚拟机中,线程优先级完全被忽略,所有线程都具有相同的优先级。
》线程中的未捕获异常
第一对方法是 getUncaughtExceptionHandler()
和 setUncaughtExceptionHandler()
,它们允许您为当前线程及其后代定制行为,从而允许二十或更多的线程拥有自己的定制行为。不过,您更可能使用第二对方法 getDefaultUncaughtExceptionHandler()
和 setDefaultUncaughtExceptionHandler()
。如果使用第二对方法设置默认处理程序,那么没有自己的异常处理程序的所有线程都将使用默认处理程序
》ReentrantLock
一个可重入的互斥锁 Lock
,它具有与使用 synchronized
方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}
Condition
await()
造成当前线程在接到信号或被中断之前一直处于等待状态。
signal()
唤醒一个等待线程。
signalAll()
唤醒所有等待线程
》Callable
有返回结果的异步计算,返回结果通过Future接口的get方法可以取得
FutureTask实现了Runnable和Callable的接口。
》线程池
通过Executors可以构建五种线程池,它们分别是newCachedThreadPool,newFixedThreadPool,newSingleThreadExecutor,newScheduledThreadPool,newSingleThreadScheduledExecutor。
使用线程池的步骤:
1.调用Executors类中的静态的newCachedThreadPool等方法。
2.调用submit或execute来提交一个Runnalbe或Callable的对象。
3.使用Future对象取得返回结果。
4.当不想再提交任何任务时,使用shutdown方法。
》后台线程
在线程启动之前,通过设置Thread.setDaemon(true)而变成后台线程,当非后台线程结束时,后台线程也随之结束,而只要非后台程序运行,程序就不会终止。
Volatile
锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility)。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 —— 如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。
如果严格遵循 volatile 的使用条件 —— 即变量真正独立于其他变量和自己以前的值 —— 在某些情况下可以使用 volatile
代替 synchronized
来简化代码。
Volatile 变量具有 synchronized
的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。Volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。因此,单独使用 volatile 还不足以实现计数器、互斥锁或任何具有与多个变量相关的不变式(Invariants)的类(例如 “start <=end”)。
出于简易性或可伸缩性的考虑,您可能倾向于使用 volatile 变量而不是锁。当使用 volatile 变量而非锁时,某些习惯用法(idiom)更加易于编码和阅读。此外,volatile 变量不会像锁那样造成线程阻塞,因此也很少造成可伸缩性问题。在某些情况下,如果读操作远远大于写操作,volatile 变量还可以提供优于锁的性能优势。
》ThreadLocal
可以为使用相同变量的不同线程都创建一个不同的存储
》多线程中的数组和集合
Collection 框架曾为 Java 程序员带来了很多方便,但在多核时代,Collection 框架变得有些不大适应。多线程之间的共享数据总是存放在数据结构之中,如 Map、Stack、Queue、List、Set 等。 Collection 框架中的这些数据结构在默认情况下并不是多线程安全的,也就是说这些数据结构并不能安全地被多个线程同时访问。 JDK 通过提供 SynchronizedCollection 为这些类提供一层线程安全的接口,它是用 synchronized
关键字实现的,相当于为整个数据结构加上一把全局锁保证线程安全。
java.util.concurrent 中提供了更加高效 collection,如 ConcurrentHashMap/Set, ConcurrentLinkedQueue, ConcurrentSkipListMap/Set, CopyOnWriteArrayList/Set 。这些数据结构是为多线程并发访问而设计的,使用了细粒度的锁和新的 Lock-free 算法。除了在多线程条件下具有更高的性能,还提供了如 put-if-absent 这样适合并发应用的原子函数。
》原子变量
java.util.concurrent.atomic 包中引入了原子变量,包括 AtomicInteger、AtomicLong、AtomicBoolean 以及数组 AtomicIntergerArray、AtomicLongArray 。原子变量保证了 ++
,--
,+=
,-=
等操作的原子性。利用这些数据结构,您可以实现更高效的计数器和随机数生成器。