Using Runnable instead of subclassing Thread Useful methods defined on the Thread class

• Were not sure what the status of the database is. Did the database get updated? Theres no way to know. • Were not going to ever enter that finally block and release the database connection. This may not be a significant resource drain in the client application, but it may be significant for the database server, especially if we have a database license that allows only a limited number of concurrent connections. For these reasons, Javasoft deprecated stop in JDK1.1 and instead recommended that people use a boolean flag inside their implementation of run . Here, for example, is a simple schema for subclassing Thread : public abstract class StoppableThread extends Thread { ... many constructors, weve only included one public StopppableThreadString threadName, Object arg1, OObject arg2 { superthreadName; use arg1, arg2, ... to initialize thread state start ; } private boolean _shouldStopExecuting; public void setShouldStopExecutingboolean shouldStopExecuting { _shouldStopExecuting = shouldStopExecuting; } public boolean getShouldStopExecuting { return _shouldStopExecuting; } public void run { while _shouldStopExecuting { performTask ; } } protected abstract void performTask ; } This defines an abstract method, performTask , and puts it inside a potentially infinite loop. As long as the instances setShouldStopExecuting method isnt called with a value of true , the loop will continue, and performTask will be executed repeatedly.

11.4.3.3 Using Runnable instead of subclassing Thread

The preceding example used a subclass of Thread to implement the run method. Another way to accomplish this is to pass in an object to Thread s constructor. This object needs to implement the Runnable interface, which consists of a single method: public void run ; Generally speaking, people prefer to do this for two reasons. The first is that its slightly cleaner™ it separates what the thread does from the instance that represents the thread. The second reason is that it preserves flexibility. In Java, a class can extend only one other class. If the class that implements run extends Thread , it cannot extend another class in your application. This can be annoying.

11.4.3.4 Useful methods defined on the Thread class

In addition to providing the ability to start and stop threads, the Thread class also contains some useful methods that enable you to have a much finer degree of control over individual threads than wait notify provide. The most important of these methods are: public static Thread currentThread ; public static void sleeplong millis; public static void yield ; public String getName ; public void setNameString name; public boolean isAlive ; public int getPriority ; public void setPriorityint newPriority; The static methods all operate on the currently executing thread. currentThread returns the instance of Thread corresponding to the currently executing thread. sleep causes the calling thread to become inactive for at least millis and quite possibly longer. Note that, while asleep, the thread retains any locks it has. And yield is a milder form of sleep ™it causes the thread to become momentarily inactive, but does not guarantee that the thread will remain inactive for any length of time. One of the more frequent programming errors using threads involves calling sleep on an instance of Thread . Java allows you to call static methods on instances of a class and simply redirects the call to the class object. This can be problematic, as programmers sometimes write lines of code such as: instanceOfthread.sleep ; which are intended to cause the instance of Thread to sleep for awhile. But this invokes the static method sleep defined on the Thread class, which will put the calling thread to sleep. setName and getName enable you to name a specific thread and find the name of a thread, respectively. These dont actually alter program functionality in any significant way but can be tremendously useful when debugging. Frequently, the first thing you need to do when something goes wrong is find out which thread is screwing up. If youve given your threads descriptive names, this becomes much easier. For example, the following line of code can be very convenient: System.out.printlnThread named + Thread.currentThread.getName + is going haywire; isAlive is a method that returns true if, when it is called, the thread associated with the instance is still alive. There is no guarantee, however, that the thread is still alive when the calling thread acts on the information. Consider, for example, the following code: if threadInstance.isAlive { do something } We could have the following sequence occur in our program: 1. The test is executed and returns true . 2. The thread associated to threadInstance expires. 3. The body of the if statement is executed. This is usually not what we want to happen. On the other hand, a return value of false , indicating that the thread has died, is reliable. Threads do not restart once dead, and once isAlive returns false, it will always return false . The final pair of useful methods is getPriority and setPriority . A thread with a higher priority usually gets more processor time. Conversely, a thread with a lower priority usually gets a smaller percentage of the processors time. However, there arent any hard and fast guarantees about this. In all of The Java Language Specification, 2nd Edition edited by Bill Joy Addison-Wesley, there is exactly one paragraph devoted to thread priorities: Every thread has a priority. When there is competition for processing resources, threads with higher priority are generally executed in preference to threads with lower priority. Such preference is not, however, a guarantee that the highest priority thread will always be running, and thread priorities cannot be used to reliably implement mutual exclusion. This means that you cant rely on priorities to guarantee program correctness. You can, however, use them as a way to hint to the JVM which threads are more important to you. And doing so is often useful. Thread has many other methods that can be useful in certain situations. And there are other classes that can be used when dealing with sets of threads. The two most useful are ThreadGroup and ThreadLocal . Both are defined in java.lang . Covering the additional methods and classes, however, is just a little too far outside the scope of this book.

11.5 Deadlock

My boss came into my office a couple of weeks ago. The database metrics arent being recorded again. I think the storage thread is running into a deadlock. Why? I asked. Server problems are always deadlocks, he replied. Technically, he was, of course, incorrect. Servers experience many other types of problems. But there was, nonetheless, a kernel of truth to what he said. Deadlock, a situation in which two or more threads block each other and force each other to wait forever, is far and away the single most common serious mistake made in writing multithreaded code. The simplest deadlock scenario involves two threads and two locks. The first thread already has the first lock and is trying to acquire the second lock. The second thread has the second lock and is trying to acquire the first lock. For example, this could be caused by two methods with the following structure: public synchronized void method1... { otherObject.method2 ;} } public synchronized void method2... { otherObject.method1 ;} } If there are two methods like this in your code, the following situation can arise: