Java Thread
创建线程
继承(extends) Thread类, 或者实现(implements) Runnable 接口, 然后实现public void run() {} 方法.
每个线程都有一个唯一的正整数 (long) 作为线程ID, 此ID在线程存活期间保持不变, 不同线程可以有相同的name
线程的启动, 停止, 暂停, 继续
启动线程, 调用 start() 方法.
Thread 的 stop(), suspend(), resume() 方法都被废弃了, 原因及替代方法看这里: http://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
线程优先级 Priority
Thread类有三个静态字段 MAX_PRIORITY, MIN_PRIORITY, NORM_PRIORITY;
如果线程实例是通过new 关键字创建出来的, 那么新线程与创建它的线程有同样的优先级.
可以通过setPriority(int newPriority) 方法改变其优先级
线程的状态
线程有6种可能的状态: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED. 这6种状态是线程的内部static Thread.State Enum所定义的.
捕获异常
由于run() 方法的声明中没有抛出任何异常, 所以任何 checked exception 都必须在run() 方法内消化掉, 对于其它的任何 unchecked exception, Throwable 都有UncaughtExceptionHandler 处理. 线程和线程组实例都可以注册UncaughtExceptionHandler. 当线程遭遇这类异常后, 退出之前, 会把线程和异常传给线程的UncaughtExceptionHandler 处理, 如果线程没有注册UncaughtExceptionHandler, 则使用线程组的UncaughtExceptionHandler 处理, 如果线程组也没有, 则使用getDefaultUncaughtExceptionHandler处理.
守护线程 Daemon Thread
setDaemon(boolean on) 设置是否为 Daemon 线程, 并且必须在线程start之前设置.
当所有的非 Daemon 线程结束之后, java 程序自动退出. 当任何一个线程执行System.exit() 指令之后, 所有线程停止运行, 并退出.
线程组 ThreadGroup
线程组包含一组线程,并且可以包含其它线程组, 也就是说可以嵌套,形成树形结构. 线程组的 interrupt()方法可以对一组线程同时发送interrupt信号.
interrupt a thread
你可以通过线程的 interrupt() 方法向线程发送 interrupt 信号.
如果该线程因调用Object 的wait()方法, Thread的sleep(), join()方法而阻塞, 同时又收到 interrupt signal的时候, 这些方法会收到一个 InterruptedException.
interrupted() 方法: 返回当前interrput 状态, 并清除interrput 状态
isInterrrupt() 方法: 只返回当前interrupt状态, 不改变其值.
更多关于收到interrupt 信号后的状态设置及变化, 参看JDK官方文档.
调用某线程的 join() 方法
A线程代码中执行B.join()方法, 会使A线程停止执行, 在此处等待B线程结束. 带有参数的 join(long, int) 会等待特定的时间. join的内部实现其实是使用Object的wait() 方法.
线程 sleep() 方法 和 Object 的wait(), notify(), notifyAll() 方法
sleep() 是静态(static)方法, 它使当前线程暂停执行特定的时间. 暂停期间并不会失去任何已占有的锁(monitor).
yield() 方法只是提示线程管理者: 我可以暂停我使用CPU, 但不一定被理会.
Object的wait() 方法会使当前线程暂停(或暂停特定时间), 但是在调用wait() 方法之前, 该线程必须获得该对象的锁 (monitor), 当开始暂停时, 释放该锁, 等待获得该锁的其他线程调用该对象的 notify 或 notifyAll 方法 (或暂停特定时间后再次获得该对象的锁), 当再次获得该对象的 monitor 之后, 继续运行. 所以一般的调用方式为:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
notify 方法也一样, 必须获得monitor 之后, 才能去notify 其它线程.
ThreadLocal 变量
ThreadLocal 对于使用它的每个线程, 创建一个线程都有的实例, 凡是同一个线程去取(get), 或去修改(set) 都是这个线程唯一的实例. 所以不存在多线程竟然(race) 读写的情况. 一般情况下ThreadLocal 变量都是声明为private static 字段.
与之向类似的用于多线程编程的有个 ThreadLocalRandom 类.