[SCJP Sun Certified Programmer for Java 6 Study Guide (Exam 310-065)] chapter9
一. 定义、实例化、启动线程
1. 线程可以通过继承 Thread 类并 overriding 方法 public void run().
2. 线程对象可以通过调用带1个Runnable参数的构造函数创建,The Runnable object is said to be the target of
the thread.
3. 1个线程对象的 start() 只能被调用1次,再次调用时将抛出 RuntimeException.
4. 用同1个 Runnable 作为目标创建多个线程对象是合法的。
5. 当1个线程对象创建后,并没有被执行,直到 start() 被调用。当1个线程对象已存在但未被启动时,它处于 new 状态,并且它不会被认为是 alive.
二. 线程状态转换
1. 当1个 new 线程已启动,则进入 runnable 状态。
2. 线程scheduler可以使线程在 runnable 和 running 状态间转换。
3. 对1个典型的单处理器机,同1时间只能运行1个线程,尽管有很多线程处于 runnable 状态。
4. 线程启动的顺序是否决定线程运行的顺序是无法确定的。(线程运行的顺序并不一定取决于线程启动的顺序。)
5. 线程是否能得到公平地轮流运行是无法确定的,这由线程scheduler决定,并取决于虚拟机实现。If you want a guarantee that your threads will take turns regardless of the underlying JVM, you can use the sleep() method. This prevents one thread from hogging the running process while another thread starves(这将给其它线程以运行的机会)。(In most cases, though, yield() works well enough to encourage your threads to play together nicely.)
6. 1个 running 线程可以通过调用其wait(), sleep(), join() 方法,而进入 blocked/waiting 状态。
7. 1个 running 线程可能会因为它不具备同步块的锁,而进入 blocked/waiting 状态。
8. 当 sleep 或 wait 已经结束,或1个对象的锁已经获得,线程只能重新进入 runnable 状态。It will go directly from waiting to running (well, for all practical purposes anyway).
9. 1个 dead 线程不能被再次启动。
三. Sleep, Yield, and Join
1. Sleeping 用于延迟执行一段时间,但不会释放锁。
2. 1个 sleeping 线程确定会 sleep一段时间(unless it's interrupted), 但当它醒来时是否会进入 running 状态是无法确定的。
3. sleep() 方法是静态的,sleep 的是当前正在执行的线程,1个线程不能让另1个线程 sleep.
4. setPriority() 方法用于设置线程优先级,从1(低)到10(高),尽管优先级是不确定的,并且不是所有 JVMs 都能识别10个级别,一些级别可能会被当做是相等的。
5. 如果没有明确地设定优先级,1个线程可能和创建它的线程具有同等的优先级。
6. yield() 方法可以引起1个 running 线程退出,当存在着具有同等优先级的 runnable 线程。但这是否会发生是无法确定的,也无法确定是否会有另1个线程被选中运行。1个线程可能 yield 后立即回到 running 状态。
7. 相对来说,比较能够确定的是,任何时刻,1个 running 线程的优先级通常不会比任何其它 runnable 线程低。如果1个较低优先级的线程 running,而1个较高优先级的线程 runnable, JVM 通常会让高优先级的线程取代低优先级的线程运行。
8. 当1个线程调用另1个线程的 join() 方法,则当前 running 线程将等待直到它 joins 的线程完成。join() 方法相当于说:"Hey thread, I want to join on to the end of you. Let me know when you're done, so I can enter the runnable state."
四. 并发访问问题和线程同步
1. synchronized 方法防止多个线程同时访问1个对象的临界方法代码。
2. 可以将 synchronized 用于方法或方法块。
3. synchronized 方法块时,必须指定1个argument that is the object whose lock you want to synchronize on.
4. 虽然1个实例的 synchronized 代码只能被1个线程访问,多个线程仍然能访问该实例对象的 unsynchronized 代码。
5. 当1个线程 sleep, 其它线程仍无法得到它占有的锁。
6. 静态方法也可以是 synchronized, using the lock from the java.lang.Class instance representing that class.
五. 对象间通过Waiting 和 Notifying 通信
1. wait() 方法相当于说:"there's nothing for me to do now, so put me in your waiting pool and notify me when something happens that I care about." 调用 wait() 方法等同于 "wait me in your pool," or "add me to your waiting list."
2. notify() 方法用于发出1个信号给1个且只有1个处于该对象的等待池中的线程。
3. notify() 方法不能指定通知哪一个等待的线程。
4. notifyAll() 方法和 notify() 方法的工作方法是相同的,唯一不同的是它给处于该对象的等待池中的所有线程都发出信号。
5. wait(), notify(), notifyAll() 必须被在 synchronized 环境中被调用。1个线程要调用1个特定对象的 wait() 或 notify() 方法,必须具有该对象的锁。
六. 线程死锁
1. Deadlocking is when thread execution grinds to a halt because the code is waiting for locks to be removed from objects.
2. 当2个对象互相等待对方的锁时,就会发生死锁。
3. Deadlocking is bad. Don't do it.
关键线程方法(斜体表示该方法是静态的)
Class Object | Class Thread | Interface Runnable |
wait() | start() | run() |
notify() | yield() | |
notifyAll() | sleep() | |
join() |