<<
Blocking Processes With Threads
I was playing at creating blocking processes with threads, so that any task can be run with a timeout. Callbacks are easier when running background processes, but not always appropriate.
Anyway, here is the test code I put together. It's really pointless. There is a blocking process which will accept a number from 0 to 10, and try and randomly generate that same number, blocking until it manages to do so. The calling class will let the blocking class run for 10 seconds before timing out.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
package threads.blocking;
/**
* I demonstrate creating blocking threads - useful for performing tasks with a timeout
*/
public class BlockingThreadTest {
public static void main( String[] args ) {
new BlockingThreadTest();
}
public BlockingThreadTest() {
// create the blocking thread
BlockingNumberGenerator b = new BlockingNumberGenerator( this, 5 );
// synchronize on this - wait() must own the lock on the object to wait - wait() releases this lock
synchronized ( this ) {
// start the blocking thread
new Thread( b ).start();
try {
// set the timeout
this.wait(10 * 1000);
} catch ( InterruptedException e ) {}
if ( ! b.success() ) {
// tell the blocking thread to stop
b.stop();
System.out.println( "TIMED OUT WHILE TRYING TO GENERATE THE NUMBER" );
} else {
System.out.println( "SUCCESSFULLY GENERATED " + b.getNumber() );
}
}
}
}
/**
* I am a REALLY pointless class. I take a reference to a calling class and take a number
* from 0 to 10, and try to randomly generate that number every second, indefinitely.
*/
class BlockingNumberGenerator implements Runnable {
private final Object caller;
private final int number;
private boolean completed;
private boolean run;
public BlockingNumberGenerator( Object _caller, int _number ) {
if ( _number > 10 || _number < 0 ) {
throw new IllegalArgumentException( "Number must be between 0 and 10" );
}
caller = _caller;
number = _number;
}
public void run() {
// stop this thread to allow the calling process to complete its setup - may be redundant
Thread.yield();
run = true;
// generate random numbers from 0 to 10 until the target number comes up
System.out.println( "GENERATING RANDOM NUMBERS UNTIL I GET A " + number );
int r = -1;
while ( run && ( r = (int) ( Math.random() * 10 ) ) != number ) {
try {
Thread.sleep( 1000 );
} catch ( InterruptedException e ) {
// interrupt() may be called by the calling thread, to indicate that a timeout has occured
}
}
if ( r == number ) {
System.out.println( "GOT A " + number + "!!" );
// set the completed flag
completed = true;
}
// tell the calling thread that we're done - notify() must own the lock on the notifed object
if ( ! Thread.interrupted() ) {
// we only need to notify the caller if they didn't interrupt us - in this case that is impossible
synchronized ( caller ) {
caller.notify();
}
}
}
/**
* I stop the generation of random numbers
*/
public void stop() {
System.out.println( "STOPPED" );
run = false;
}
/**
* @return if I was able to randomly generate the desired number
*/
public boolean success() {
return completed;
}
/**
* @return the number I was able to randomly generate, or -1
*/
public int getNumber() {
return success() ? number : -1;
}
}