当前位置:编程学习 > JSP >>

Java Thread Programming 1.8.1 - Inter-thread Communication

答案:The Need for Inter-thread Signaling
 
Through synchronization, one thread can safely change values that another thread will read. How does the second thread know that the values have changed? What if the second thread is waiting for the values to change by rereading the values every few seconds?
 
One not-so-good way that a thread can wait for a value to change is by using a busy/wait:
while ( getValue() != desiredValue ) {
Thread.sleep(500);
}
 
Such code is called a busy/wait because the thread is busy using up processor resources to continually check to see if the value has changed. To use fewer resources, the sleep time could be increased, but then the thread might not find out about the change for quite some time. On the other hand, if the sleep time is reduced, the thread will find out sooner, but will waste even more of the processor resources. In Java, there is a much better way to handle this kind of situation: the wait/notify mechanism.
 
有时候我们需要线程间的通讯,比如第二个线程如何知道第一个线程的某些值发生了改变?不太好的方法如上,称之为busy/wait,通过不断循环并结合Thread.sleep()测试值是否发生变化,会占用处理器资源,并且循环的频率不容易掌握,快了浪费资源,慢了降低反应速度。像这种情况,java中给出了一种更好的解决方法:wait/notify机制
 
The Wait/Notify Mechanism
 
The wait/notify mechanism allows one thread to wait for a notification from another thread that it may proceed.
 
Minimal Wait/Notify
At a bare minimum, you need an object to lock on and two threads to implement the wait/notify mechanism.
Imagine that there is a member variable, valueLock, that will be used for synchronization:
private Object valueLock = new Object();
The first thread comes along and executes this code fragment:
synchronized ( valueLock ) {
try {
        valueLock.wait();
} catch ( InterruptedException x ) {
        System.out.println(“interrupted while waiting”);
}
}
 
The wait() method requires the calling thread to have previously acquired the object-level lock on the target object. In this case, the object that will be waited upon is valueLock, and two lines before the valueLock.wait() statement is the synchronized(valueLock) statement. The thread that invokes the wait() method releases the object-level lock and goes to sleep until notified or interrupted. If the waiting thread is interrupted, it competes with the other threads to reacquire the object-level lock and throws an InterruptedException from within wait(). If the waiting thread is notified, it competes with the other threads to reacquire the object-level lock and then returns from wait().
 
Wait()方法需要在获得object-level lock之后才能调用,否则会抛出IllegalMonitor-
StateException异常,当线程调用wait()方法后,会释放object-level lock,然后sleep(),直到被notified或interrupted,如果被interrupted,此线程会重新竞争获得object-level lock,然后抛出InterrruptedException,如果被notified,此线程会重新竞争获得object-level lock,从wait()返回,继续执行wait()以后的代码。
 
Many times, a thread is interrupted to signal it that it should clean up and die (see Chapter 5). The statements used to wait can be slightly rearranged to allow the InterruptedException to propagate up further:
 
try {
synchronized ( valueLock ) {
        valueLock.wait();
}
} catch ( InterruptedException x ) {
System.out.println(“interrupted while waiting”);
// clean up, and allow thread to return from run()
}
 
有时候,中断一个线程是为了将其销毁清除,可以将InterruptedException异常延迟处理
 
Instead of catching InterruptedException, methods can simply declare that they throw it to pass the exception further up the call chain:
 
public void someMethod() throws InterruptedException {
// ...
synchronized ( valueLock ) {
        valueLock.wait();
}
// ...
}
 
如果不在方法内捕捉异常,可以继续上抛,留待以后处理
 
The thread doing the notification comes along and executes this code fragment:
synchronized ( valueLock ) {
valueLock.notify();  // notifyAll() might be safer...
}
 
This thread blocks until it can get exclusive access to the object-level lock for valueLock. After the lock is acquired, this thread notifies one of the waiting threads. If no threads are waiting, the notification effectively does nothing. If more than one thread is waiting on valueLock, the thread scheduler arbitrarily chooses one to receive the notification. The other waiting threads are not notified and continue to wait. To notify all waiting threads (instead of just one of them), use notifyAll() (discussed later in this chapter).
 
首先要获得object-level lock,然后调用notify()通知此object-level lock上所有等待线程中的一个,如果没有waiting线程,则通知无效。如果有多个等待线程,则线程调用机制选择其中一个通知,其它没有获得通知的继续等待。如果要通知所有此锁上的等待线程,适用notifyAll()
 
Typical Wait/Notify
 
In most cases, a member variable is checked by the thread doing the waiting and modified by the thread doing the notification. The checking and modification occur inside the synchronized blocks to be sure that no race conditions develop.
 
大部分情况下,都是一个线程等待一个成员变量满足某个条件,另一个线程修改此成员变量后进行通知。
 
This time, two member variables are used:
 
private boolean value = false;
private Object valueLock = new Object();
 
The value variable is checked by the thread doing the waiting and is set by the thread doing the notification. Synchronization on valueLock controls concurrent access to value.
 
The first thread comes along and executes this code fragment:
try {
synchronized ( valueLock ) {
        while ( value != true ) {
            valueLock.wait();
        }
        // value is now true
}
} catch ( InterruptedException x ) {
System.out.println(“interrupted while waiting”);
}
 
After acquiring the object-level lock for valueLock, the first thread checks value to see if it is true. If it is not, the thread executes wait(), releasing the object-level lock. When this thread is notified, it wakes up, reacquires the lock, and returns from wait(). To be sure that it was not falsely notified (see the “Early Notification” discussion later in this chapter), it re-evaluates the while expression. If value is still not true, the thread waits again. If it is true, the thread continues to execute the rest of the code inside the synchronized block.
 
While the first thread is waiting, a second thread comes along and executes this code fragment:
 
synchronized ( valueLock ) {
value = true;
valueLock.notify();  // notifyAll() might be safer...
}
 
When the first thread executes the wait() method on valueLock, it releases the object-level lock it was holding. This release allows the second thread to get exclusive access to the object-level lock on valueLock and enter the synchronized block. Inside, the second thread sets value to true and invokes notify() on valueLock to signal one waiting thread that value has been changed.
 
Wait/Notify with synchronized Methods
 
Sometimes, the class is designed to synchronize on this instead of another object. In this case, the synchronized method modifier can be used instead of a synchronized statement. The following code fragments are an adaptation of the previous example.
 
如果不是同步其它对象,而是同步this,可以类定义中结合wait/n

上一个:Java Thread Programming 1.8.2 - Inter-thread Communication
下一个:Java Thread Programming 1.7 - Concurrent Access to Objects and Variables

CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,