| 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:
|
| 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:
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 | |
|---|---|
| New | Created, but not yet started. |
| Runnable | Eligible to run, but not running. |
| Running | Currently executing. |
| Waiting/blocked/sleeping | Not runnable, but might be runnable later, after a resource is available, or it's notified, or the time is up, or it's interrupted. |
| Dead | run() 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.
Here are some bits to keep in mind regarding synchronization:
|
|
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:
|