The Java tips presented here are tips that vary in complexity from easy for newer Java developers to more complicated tips for experienced developers. The one thing they all have in common is that they do not require any external frameworks - they are all based around Java standard APIs and frameworks.
Concurrency
This tip takes a look at the java.util.concurrent package and how it can be easily applied where simple concurrency between objects is required. The code is downloadable here
In our simple example we have two threads that need to be synchronised, so that one thread tells the other when it can do something - using java.util.concurrent.SynchronizedQueue. That something would probably involve operating on the Object that has been placed on to the SynchronizedQueue
Firstly import required classes and code the main method:
1 import java.util.concurrent.SynchronousQueue;
2 import java.util.concurrent.TimeUnit;
3 import java.io.BufferedReader;
4 import java.io.InputStreamReader;
5 import java.io.IOException;
6
7 public class SyncTest {
8
9 public static void main(String[] args) throws InterruptedException {
10 SynchronousQueue syncQ = new SynchronousQueue();
11 SyncTest me = new SyncTest();
12
13 PutOnQ pq = me.new PutOnQ(syncQ);
14 TakeOffQ tq = me.new TakeOffQ(syncQ);
15
16 Thread putter = new Thread(pq);
17 Thread taker = new Thread(tq);
18 putter.start();
19 taker.start();
20
21 taker.join();
22 System.out.println("State of \'take queue\' is: " +
23 taker.getState() +
24 ". State of \'put queue\' is " +
25 putter.getState());
26 putter.join();
27 System.out.println("State of \'take queue\' is: " +
28 taker.getState() +
29 ". State of \'put queue\' is " +
30 putter.getState());
31 }
Notice the delcaration on line 10. The SynchronizedQueue is going to manage a String, it could of course be any object.
The statements from Line 21 through to the end of the main method are there to simply illustrate the functionality of the SynchronizedQueue. For those who have forgotten, line 21 causes the main thread to wait until the taker thread terminates, line 26 does the same for the putter thread.
Then the inner class that handles the putting of data:
32
33 class PutOnQ implements Runnable {
34 private SynchronousQueue sq;
35
36 public PutOnQ(SynchronousQueue queue) {
37 sq = queue;
38 }
39
40 public void run() {
41 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
42 try {
43 String s = "";
44 do {
45 s=br.readLine();
46 System.out.println(Thread.currentThread().getName() +
47 " offering " + s);
48 } while ( sq.offer(s, 10L, TimeUnit.SECONDS));
49 }
50 catch (InterruptedException e){}
51 catch (IOException e){}
52 }
53 }
In our example the run method does all the work, it gets a String from the keyboard and places it on the SynchronizedQueue.
The while statement uses the offer method of the SynchronizedQueue class to offer the string to any waiting thread, if nothing is taken by the time 10 seconds is up then the loop terminates and thus the run method terminates.
The next inner class deals with retrieving the contents of the queue:
54
55 class TakeOffQ implements Runnable {
56 private SynchronousQueue sq;
57
58 public TakeOffQ(SynchronousQueue queue) {
59 sq = queue;
60 }
61
62 public void run() {
63 String s = "";
64 while (s != null) {
65 try {
66 s = sq.poll(10L, TimeUnit.SECONDS);
67 System.out.println(Thread.currentThread().getName() +
68 " Got " + s);
69 }
70 catch (InterruptedException e){}
71 }
72 System.out.println("Timed out waiting for a string");
73 }
74 }
75 }
Line 66 is where all the work takes place. We poll the queue to see if there is something there, if there is we take it off the queue and use it (in our case the string is printed) otherwise the loop terminates.
Compile the code and execute.
Test #1
laptop:~$ java SyncTest
hello
Thread-0 offering hello
Thread-1 Got hello
goodbye
Thread-0 offering goodbye
Thread-1 Got goodbye
nothing
Thread-0 offering nothing
^CThread-1 Got nothing
laptop:~$
We simply typed in strings and pressed the enter key.
Test #2
This time type in only one string and wait to see what happens (hint: you'll have to wait ten seconds!)
laptop:~$ java SyncTest
string#1
Thread-0 offering string#1
Thread-1 Got string#1
Thread-1 Got null
Timed out waiting for a string
State of 'take queue' is: TERMINATED. State of 'put queue' is RUNNABLE
Thread-1 got the first string we entered, then entered the poll method (line 66), but timed out and thus caused the thread to terminate.
Test #3
Without terminating the program just press the enter key and wait.
Thread-0 offering
State of 'take queue' is: TERMINATED. State of 'put queue' is TERMINATED
laptop:~$
Thread-0 offers up the object to any waiting thread, but becasue there is no thread waiting to retrieve the data thread-0 only waits for ten seconds then terminates.
Summary
In summary the SynchronizedQueue class can be useful where synchronisation between two threads that perform operations on the same object is required.