ExceptionListener Interface

Chapter 14 - Waiting for the Full Timeout

Java Thread Programming
Paul Hyde
  Copyright 1999 Sams Publishing

A General-Purpose Wait-Until Pattern
In this section, Ill show you a more complete example that can be used as a model and expanded to fit your real-world needs when a wait-until scenario is needed. The main enhancement is to allow a timeout of to be passed in just as wait() allows.
On Object , a call to
public final void wait() throws InterruptedException
behaves as if was passed into
public final void wait(long timeout) throws InterruptedException
in the sense that it waits until notified, regardless of how much real time elapses. FullWait , shown in Listing 14.4, expands upon EarlyNotifyFix to allow msTimeout to be when invoking waitUntilAtLeast() to indicate that the thread should not return until the minimum is reachedregardless of how much time elapses.
Listing 14.4  FullWait.javaA Good Base Design Pattern to Use for Wait-Until Situations
1: public class FullWait extends Object {
2:     private volatile int value;
3:
4:     public FullWait(int initialValue) {
5:         value = initialValue;
6:     }
7:
8:     public synchronized void setValue(int newValue) {
9:         if (value != newValue) {
10:             value = newValue;
11:             notifyAll();
12:         }
13:     }
14:
15:     public synchronized boolean waitUntilAtLeast(
16:                 int minValue,
17:                 long msTimeout
18:            ) throws InterruptedException {
19:
20:         if (msTimeout == 0L) {
21:             while (value < minValue) {
22:                 wait();  // wait indefinitely until notified
23:             }
24:
25:             // condition has finally been met
26:             return true;
27:         }
28:
29:         // only wait for the specified amount of time
30:         long endTime = System.currentTimeMillis() + msTimeout;
31:         long msRemaining = msTimeout;
32:
33:         while ((value < minValue) && (msRemaining > 0L)) {
34:             wait(msRemaining);
35:             msRemaining = endTime - System.currentTimeMillis();
36:         }
37:
38:         // May have timed out, or may have met value,
39:         // calc return value.
40:         return (value >= minValue);
41:     }
42:
43:     public String toString() {
44:         return getClass().getName() + [value= + value + ];
45:     }
46: }
FullWait is based upon EarlyReturnFix with the main() method and the informational messages removed. The waitUntilAtLeast() method (lines 1541) has been expanded to support a timeout of .
If msTimeout is equal to (line 20), the while loop continues to wait() until the minimum value has been met (lines 2123). If the minimum was met before waitUntilAtLeast() was invoked, the while loops body is never executed, and true is returned. Otherwise, the body of the while loop is executed and the thread waits until notified (line 22). Every time setValue() is called with a new value, any and all waiting threads are notifiedregardless of what value was set. This means that the wait() (line 22) might be notified before the minimum is met. If this happens, the while loop will simply execute again, causing the thread to go into another wait-until-notified state. If the minimum is ever met, the while loop will terminate and true will be returned (line 26).
If msTimeout is non-zero , waitUntilAtLeast() will behave exactly as it did in EarlyReturnFix (see detailed description earlier). It will continually wait until either the timeout has been reached, or the minimum has been met (lines 3040).
FullWaitMain in Listing 14.5 constructs a FullWait and demonstrates different scenarios.
Listing 14.5  FullWaitMain.javaCode to Demonstrate FullWait
1: public class FullWaitMain extends Object {
2:     private FullWait fullwait;
3:     private Thread internalThread;
4:     private volatile boolean noStopRequested;
5:
6:     public FullWaitMain(FullWait fw) {
7:         fullwait = fw;
8:
9:         noStopRequested = true;
10:         Runnable r = new Runnable() {
11:                 public void run() {
12:                     try {
13:                         runWork();
14:                     } catch (Exception x) {
15:                         x.printStackTrace();
16:                     }
17:                 }
18:             };
19:
20:         internalThread = new Thread(r);
21:         internalThread.start();
22:     }
23:
24:     private void runWork() {
25:         int count = 6;
26:
27:         while (noStopRequested) {
28:             fullwait.setValue(count);
29:             System.out.println(just set value to + count);
30:             count++;
31:
32:             try {
33:                 Thread.sleep(1000);
34:             } catch (InterruptedException x) {
35:                 // reassert interrupt
36:                 Thread.currentThread().interrupt();
37:             }
38:         }
39:     }
40:
41:     public void stopRequest() {
42:         noStopRequested = false;
43:         internalThread.interrupt();
44:     }
45:
46:     public boolean isAlive() {
47:         return internalThread.isAlive();
48:     }
49:
50:     public static void waitfor(FullWait fw, int val, long limit)
51:                 throws InterruptedException {
52:
53:         System.out.println(about to waitUntilAtLeast(+
54:                 val + , + limit +) ...);
55:
56:         long startTime = System.currentTimeMillis();
57:         boolean retVal = fw.waitUntilAtLeast(val, limit);
58:         long endTime = System.currentTimeMillis();
59:
60:         System.out.println(waited for +
61:                 (endTime - startTime) +
62:                 ms, retVal= + retVal + \n---------------);
63:     }
64:
65:     public static void main(String[] args) {
66:         try {
67:             FullWait fw = new FullWait(5);
68:             FullWaitMain fwm = new FullWaitMain(fw);
69:
70:             Thread.sleep(500);
71:
72:             // should return true before 10 seconds
73:             waitfor(fw, 10, 10000L);
74:
75:             // should return true right away --already >= 6
76:             waitfor(fw, 6, 5000L);
77:
78:             // should return true right away
79:             //   --already >= 6 (negative time ignored)
80:             waitfor(fw, 6, -1000L);
81:
82:             // should return false right away --not there
83:             // yet & negative time
84:             waitfor(fw, 15, -1000L);
85:
86:             // should return false after 5 seconds
87:             waitfor(fw, 999, 5000L);
88:
89:             // should eventually return true
90:             waitfor(fw, 20, 0L);
91:
92:             fwm.stopRequest();
93:         } catch (InterruptedException x) {
94:             System.err.println(*unexpectedly* interrupted +
95:                     somewhere in main());
96:         }
97:     }
98: }
In main() , a FullWait object is constructed with an initial value of 5 (line 67). This object is passed as a parameter to the constructor of FullWaitMain (line 68). The main thread then sleeps to let the internal thread get up and going (line 70). This sleep is not a critical step, but helps ensure that the other thread has a chance to run for a little bit (about half a second) before the waiting begins.
The constructor for FullWaitMain (lines 622) stores the reference to the FullWait object, starts the internal thread running, and then returns. The internal thread invokes runWork() (lines 2439). In the while loop inside runWork() , the thread invokes the setValue() method on the FullWait object (line 28). Initially, it passes 6 to setValue() and then sleeps for one second (line 33). Each time through the while loop, the value passed is incremented by 1 (line 30). The internal thread continues to increment the value once per second until a stop request is received.
Back in main() , several calls to the static method waitFor() are made. The waitFor() method (lines 5063) is used to call waitUntilAtLeast() on the FullWait object. Each time informational messages are printed, the time spent inside waitUntilAtLeast() is measured, and the return value is captured.
The first waitFor() call (line 73) waits for up to 10 seconds for the value to reach 10 . The value should be at about 6 when this is called, and because it increments once each second, it should easily reach a minimum value of 10 before the timeout.
The next call (line 76) waits for the value to reach 6 , but it is already at least 10 , so it returns true right away. The next call (line 80) passes a negative timeout value, but because the minimum value passed is 6 and it has already been reached, it should return true right away and ignore the negative timeout. The next call (line 84) passes in a minimum of 15 (which has not yet been reached) and a negative timeout. The negative timeout causes it to return right away, and because the minimum was not reached, false is returned. The next call (line 87) will only wait five seconds for the value to reach 999 . This wont happen in that time, so after five seconds, it returns false . The last call (line 90) specifies a minimum of 20 and a timeout of . A timeout of will cause it to wait indefinitely until the minimum value is reached. A few seconds later, 20 is reached, and true is returned.
For cleanup purposes, stopRequest() is called (line 92) to shut down the internal thread. Most of main() is in a try / catch block (lines 6696) because an InterruptedException might be thrown. In this case, this occurrence is quite unexpected and a message to that effect is printed if it happens (lines 9495).
Listing 14.6 shows output from a particular run of FullWaitMain . Your times will probably vary from this a bit, but the true and false return values should match exactly for each of the scenarios.
Listing 14.6  Sample Output from Running FullWaitMain (Your Output Will Differ )
1: just set value to 6
2: about to waitUntilAtLeast(10, 10000) ...
3: just set value to 7
4: just set value to 8
5: just set value to 9
6: just set value to 10
7: waited for 3630 ms, retVal=true
8: ---------------
9: about to waitUntilAtLeast(6, 5000) ...
10: waited for 0 ms, retVal=true
11: ---------------
12: about to waitUntilAtLeast(6, -1000) ...
13: waited for 0 ms, retVal=true
14: ---------------
15: about to waitUntilAtLeast(15, -1000) ...
16: waited for 0 ms, retVal=false
17: ---------------
18: about to waitUntilAtLeast(999, 5000) ...
19: just set value to 11
20: just set value to 12
21: just set value to 13
22: just set value to 14
23: waited for 5000 ms, retVal=false
24: ---------------
25: about to waitUntilAtLeast(20, 0) ...
26: just set value to 15
27: just set value to 16
28: just set value to 17
29: just set value to 18
30: just set value to 19
31: just set value to 20
32: waited for 5050 ms, retVal=true
33: ---------------

Toc


Java Thread Programming
Java Thread Programming
ISBN: 0672315858
EAN: 2147483647
Year: 2005
Pages: 149
Authors: Paul Hyde

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net