Stopping Threads


A testing flaw still remains in ServerTest. The thread in the Server class is executing an infinite loop. Normally, the loop would terminate when the Server itself terminated. When running your tests in JUnit, however, the thread keeps running until you close down JUnit itselfthe Server run method keeps chugging along.

The Thread API contains a stop method that would appear to do the trick of stopping the thread. It doesn't take long to read in the detailed API documentation that the stop method has been deprecated and is "inherently unsafe." Fortunately, the documentation goes on to explain why and what you should do instead. (Read it.) The recommended technique is to simply have the thread die on its own based on some condition. One way is to use a boolean variable that you initialize to true and set to false when you want the thread to terminate. The conditional in the while loop in the run method can test the value of this variable.

You will need to modify the ServerTest method tearDown to do the shutdown and verify that it worked.

 protected void tearDown() throws Exception {    assertTrue(server.isAlive());    server.shutDown();    server.join(3000);    assertFalse(server.isAlive());    TestUtil.delete(SearchTest.FILE); } 

Remember, the tearDown method executes upon completion of each and every test method, regardless of whether or not an exception was thrown by the test. In tearDown, you first ensure that the thread is "alive" and running. You then send the message shutDown to the server. You've chosen the method name shutDown to signal the server to stop.

You then wait on the server thread by using the join method, with an arbitrary timeout of 3 seconds. It will take some time for the thread to terminate. Without the join method, the rest of the code in tearDown will likely execute before the thread is completely dead. Finally, after you issue the shutDown command to the Server, you ensure that its thread is no longer alive. The isAlive method is defined on Thread and Server is a subclass of Thread, so you can send the message isAlive to the Server instance to get your answer.

Since the Server class now uses a LinkedBlockingQueue, you cannot use a boolean flag on the run method's while loop. The LinkedBlockingQueue take method blocksit waits until a new object is available on the queue. It would wait forever if you left JUnit running.

One way you could get the LinkedBlockingQueue to stop waiting would be to put a special Search object on the queue, one that signifies that you're done. Each time you take an object from the queue, you would need to check to see if it was the special Search object and terminate the run method if it was.

Another way to stop LinkedBlockingQueue from waiting is to interrupt the thread by sending it the interrupt message, which generates an Interrupted-Exception. If you catch an InterruptedException, you can then break out of the infinite while loop. Here is the implementation of this approach:

 public class Server extends Thread {    // ...    public void run() {       while (true)          try {             execute(queue.take());          }          catch (InterruptedException e) {             break;          }    }    // ...    public void shutDown() throws Exception {       this.interrupt();    } } 



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

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