Threads
JVM exits an application only when all user threads are complete, ignoring the state of all daemon threads.
You should call the 'start()' method on a thread object, to get it to run. This causes the JVM to fire up the run() method in a separate thread. If you call 'run()' by accident instead, it will work, but it will run in the current thread, not a separate thread.
You could extend this class, and override the 'run' method to get your code to run, but then your class couldn't extend anything else! A cleaner way is to make your class implement the Runnable interface instead.
Thread Methods
constructor Thread()Allocates a new Thread object, and assigns an automatically generated name.
constructor Thread(Runnable target)Allocates a new Thread object, and assigns an automatically generated name. When start() is called, it will call the run() method of the supplied Runnable.
constructor Thread(Runnable target, String name) Allocates a new Thread object, and gives it the supplied name. When start() is called, it will call the run() method of the supplied Runnable.
constructor Thread(String name)Allocates a new Thread object, and gives it the supplied name.
public void join()
throws InterruptedException
Waits for this thread to die die DIE.
public void join(long millis)
throws InterruptedException
Waits at most millis milliseconds for this thread to die die DIE. A timeout of 0 means to wait forever.
public String getName()Return this thread's name.
public void setPriority(int newPriority) By default, a thread has the priority of the thread of execution that created it; ie, a thread created by main will have a priority that is the same as thread main. This routine allows you to change the priority of the thread.

Acceptable values include:

  • Thread.MIN_PRIORITY
  • Thread.NORM_PRIORITY (default)
  • Thread.MAX_PRIORITY
or a number from 1 to 10, where 1 is the minimum priority, and 10 is the maximum priority.
public void run()If this thread was constructed using a separate Runnable run object, then that Runnable object's run method is called; otherwise, this method does nothing and returns.
public void start()Causes this thread to begin execution;
public static void yield() Causes the currently executing thread object to temporarily pause and allow other threads to execute.

This behavior is not guaranteed, plus there's nothing to stop the scheduler from picking the exact same thread again for execution. Don't rely on this routine.

public static void sleep(long millis)
throws InterruptedException
Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds. The thread does not lose ownership of any monitors. Just because a thread's sleep() expires and it wakes up, does not mean it will start running! It will simply return to 'runnable' state.
public static Thread currentThread() Returns a reference to the currently executing thread object.

Runnable
The best way to create threads, is to:
  • Implement the Runnable interface in your own code.
  • Create a Thread object that takes your Runnable in the constructor
  • Call the thread's 'start()' method.
Just creating a Runnable object isn't enough to run it - you must create a Thread object as well, and pass the runnable to it in the constructor, then call start().

You can pass the same Runnable object to multiple threads - they will all execute the very same job, and probably tromp all over each other while they're at it, unless you have been careful with synchronization.

Runnable Methods
public void run() When an object implementing interface Runnable is used to create a thread, starting the thread causes the object's run method to be called in that separately executing thread.

Object Methods
public void wait() throws InterruptedException Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.
public void wait(long timeout) throws InterruptedException Causes the current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time (in milliseconds) has elapsed.
public void notify() Wakes up a single thread that is waiting on this object's monitor.
public void notifyAll() Wakes up all threads that are waiting on this object's monitor.

Thread States
NewCreated, but not yet started.
RunnableEligible to run, but not running.
RunningCurrently executing.
Waiting/blocked/sleepingNot runnable, but might be runnable later, after a resource is available, or it's notified, or the time is up, or it's interrupted.
Deadrun() method is completed. A dead thread can never be started again - if you do, you'll get a runtime exception.

Synchronization
Synchronization is achieved in Java through locks. Every object has a lock that is only used when the object has synchronized method code. When a method with the keyword 'synchronized' is executed, the lock is automatically acquired on 'this', the current instance. Sometimes 'this' is referred to as 'monitor', and it refers to the object whose lock is being acquired.

  • Every object has a lock.
  • If no thread has the lock on this object, the currently executing thread automatically acquires the lock.
  • If another thread has the lock on this object, the currently executing thread is blocked until the other thread releases its lock.
Think of it as a bathroom door. If the door is locked, you must wait until the current person (thread) leaves it. Then, you may enter the bathroom and lock the door yourself. While you're in there, no one else may enter (you have the door locked.) When you unlock the door and leave, it's up for grabs - the next person in line for it may get it, or someone may cut the line and elbow their way in - there's no guarantee as to who will get the lock next, and you really don't care, either.

Here are some bits to keep in mind regarding synchronization:

  • Only methods or blocks can be synchronized - not variables, or classes.
  • Each object has only one lock.
  • A class can contain both synchronized and unsynchronized methods. Even if there's a lock on the object because a thread is currently executing synchronized code, another thread can be executing the unsynchronized code, at the same time. Think of a bathroom door that's locked, but there's a sink right outside the door without a door or lock - anyone can use that while you're in the bathroom.
  • A thread that's sleeping does NOT release its locks.
  • A thread can acquire more than one lock. For example, you could lock yourself in the bathroom, acquiring the bathroom lock, then log on to World of Warcraft, 'locking' your username as in use on the game.
  • You can attempt to acquire the lock more than once - it doesn't harm anything. Only the one lock is in effect. Think of it as twisting the lock closed when it's already closed - it doesn't hurt, though it DOES takes a little time. It changes nothing, because there's still only the one lock, and a single unlock will be enough to release it.
  • You can synchronize on a block of code within a method, rather than the entire method itself. When you synchronize on the block of code instead of the method, you can choose to synchronize on the current instance (this), or you could use a third-party object as the lock for this block of code.
  • You can synchronize specify the synchronized keyword on static methods in addition to instance methods. When you obtain a lock when entering the the static method, you're really obtaining the lock on the class itself - MyClass.class, for instance.
So, in short -
  • Threads get their own copy of local variables. Two threads executing the same method at the same time don't have to worry about competing for local variables, just instance and static variables.
  • Threads calling synchronized methods on the same object, will block. If they're calling synchronized methods on separate objects, they won't block.
  • Threads calling static synchronized methods on the same class, will block. If they're calling synchronized static methods for separate classes, they won't block.
  • Threads calling static synchronized methods, and normal synchronized methods, won't interfere with each other, because they're blocking on different things - the class, versus the instance of the class.
  • For synchronized blocks, look at the object that is being used for the lock - threads that attempt to synchronize on the same object, will block; and if they're attempting to synchronize on different objects, they won't.
This implies that there could be some overlap, if an instance method is changing a value on a static variable. To keep things straight, access static variables from static synchronized methods, and access non-static variables from instance synchronized methods.
Using thread-safe classes in the Java API, does not guarantee thread safety! Any time you have to execute two methods on the class, such as checking the size of the list, then removing an element if the size > 0, you could run into concurrency problems. Only one step is thread safe, by itself - you can't call one, then call another, and expect the set of two operations to be thread-safe!

To solve this problem, keep this in mind: Whenever two steps or more are required to complete an add/update/delete operation, you should not rely on the Java collection synchronization to save you; you should also create a higher level method that calls both routines, and synchronize that method.

Deadlock
Deadlock can occur when thread A is waiting for thread B to give up its lock, and thread B is waiting for thread A to give up its lock. Think of it as an employee, who says he'll work harder when he gets more money; and a boss, who says he'll give the employee more money when he works harder. Pop quiz: When will the empoyee get more money? Never. When will the boss get more work? Never. They're locked in deadly combat. Don't do this, it could cause your program to hang.

Here's a way that could happen: Thread 1 wants objects A and B, and thread 2 wants objects B and A. Since they're going for different objects, they both succeed in getting what they want - Thread 1 gets A, and thread 2 gets B. Now with the desired object in one hand, they try to get the OTHER object with their other hand - only to discover it's locked. Since they both want what each other have, neither one will ever win. One way to avoid this, is if there's a 'set' of locks you need to acquire to perform a task, always acquire the locks in the same order. If they both reached for object A at first, they wouldn't have deadlocked.

wait, notify, and notifyAll
wait, notify, and notifyAll are object methods, so they're available to all Java objects. Calling wait on an object, causes the current thread to release its lock on that object, and wait until another thread invokes the notify() method or the notifyAll() method for that object.

wait, notify, and notifyAll, must all be called from a synchronized context! If you aren't in a synchronized context, you'll get the runtime error "IllegalMonitorStateException."

Note that wait is available for all objects, including threads themselves. You could see 'wait' on a normal object, or you could see 'wait' on a thread object - both are valid.

Once a thread calls 'wait' on an object, it releases its lock on its object. Several things could jog it awake - the resource could be available, or the wait timeout may have expired. The point is, when it wakens, it won't necessarily have the lock it released. You should put the synchronized wait with the InterruptedException handler in a loop, so if it doesn't have the lock it needs, it can go back to blocked status - ie, waiting for the lock to be released.

When a thread calls 'notify' or 'notifyAll' on an object, it won't release the lock on that object immediately! The lock won't be released until the currently executing code leaves the synchronized block.

Here's a handy example to help you remember how to use these methods:

  • wait() is called by someone that needs the bathroom, but isn't in an urgent rush for it. They're hanging around the door, patiently waiting for it to open, nodding off, perhaps snoring.
  • wait(10000) is called by a young girl with a more urgent need to use the facilities, who can wait only 10 SECONDS for the bathroom before giving up and trying a different bathroom (perhaps the men's bathroom!)
  • Calling 'notifyAll' is like shouting out through the locked door 'I'll be out in a second!' You may or may not take one second to leave the bathroom, but it gets people to perk up and pay attention to the bathroom door again (wakes the threads, and they start trying to get the lock again). In actuality, your current business might cause you take another 5 minutes in there. In other words, the 'notifyAll' isn't a guarantee you'll be done soon, it just gives a heads up to people that might be waiting for it. The lock won't be released until you leave the bathroom (leave the synchronized block of code.)
  • Calling 'notify' is like whispering, so only one person in the waiting room can year you, that the bathroom will be available soon. You don't know who that person is, and can't specify which one to notify.
Here's an example that should help you remember to get a synchronized context, before calling wait, notify, or notifyAll (ie, bothering people.)
  • Calling 'wait' outside a synchronized context, is like saying 'I have to go to the bathroom' when you're nowhere near a bathroom! Which bathroom do you want to use? You have to pick a bathroom (synchronize on the object) before you can call 'wait.' This throws a runtime exception.
  • Calling 'notifyAll' outside a synchronized context, is like shouting out to everyone 'The bathroom is available, you may enter now!' when you're not in the bathroom. They don't care, because you're not even IN the bathroom. They only care when the door unlocks. This throws a runtime exception.
  • Calling 'notify' outside a synchronized context, is like telling one person 'The bathroom is available, you may enter now' when you're not in the bathroom. They don't care, because you're not even IN the bathroom. They only care when the door unlocks. This throws a runtime exception.
  • Forgetting to put the 'wait' in a loop, could result in the following: A person is waiting for the bathroom, and awakes when they hear the call of 'Almost done!' Someone leaves the bathroom, and you rush over trying to get it... only to have a third person beat you to it. So, you walk away, even though you still have to go to the bathroom. You have not used the bathroom - why are you walking away? The correct behavior is "Dang, someone else beat me to it!" and continue to wait - ie, start at the beginning of the loop, and synchronize on the bathroom again, until your turn comes.