- Java Concurrency
- Threads
- Runnables
- Thread Termination
- Thread Control
- Thread Status
- Each Java thread is like a sequential Java program.
- A collection of Java threads is a concurrent Java program.
- There is no global state for a thread to access.
- A thread accesses (references to) class instances.
- Threads may share access to (references to) class instances.
- The JVM is a weak concurrent system.
- Weak systems make fewer promises, less useful promises.
- Weak systems are easy to build, but hard to use.
- Weak systems allow much variation among implementations.
- Also, the JVM is not a well-defined weak system.
- Like most things in Java, a thread is an instance of a class.
- The Thread class, which is rarely subclassed.
- A Thread instance represents a generic execution engine.
- By default, threads do no useful computations.
- Create a thread with
new, like any Java class instance.
- A thread is dormant when created.
- Thread
t begins executing when t.start() is called.
-
public void start() throws IllegalThreadStateException.
-
t.start() eventually calls t.run().
- Thread
t does specific work by calling t.run().
-
public void run().
- Whatever goes on inside
t.run() is the real work of the thread.
- There are many other constructors, members and fields.
- Threads and runnables are complimentary.
- Threads have the ability but don't have the knowledge.
- Runnables have the knowledge but don't have the ability.
- The combination of Threads and Runnables leads to concurrent Java
programs.
- The Thread class implements the Runnable interface.
- Runnables are defined in
java.lang.Runnable
- The thread-default Runnable implementation does nothing.
See the complete code.
- Thread
t terminates when t.run() returns.
- Once it terminates, a thread can't be revived.
-
start() will throw an Illegal Thread State Exception.
- The runnable (if explicit) is another matter.
- Threads are garbage collected, with all the problems that entails.
- Timeliness (finalization and all that).
- Forgotten and unneeded thread references.
- Inducing premature termination is a tricky and delicate matter.
- Exceptions are not the answer.
- Better left to the Runnable implementation.
-
t.stop() asynchronously terminates thread t.
- Dangerous - releases locks without clean-up.
- Depreciated as of Java 1.2.
-
t.destroy() immediately terminates thread t.
- Dangerous - no resource clean up; no locks are released.
- Never implemented.
- The
Thread Death exception.
- An internal mechanism that escaped.
- Don't use any of these.
- Make termination a synchronization condition in your Runnable.
- Do not control threads directly; control the tasks they execute.
- Example - implementing mutual exclusion.
- Bad - Set maximum thread priority to get mutual exclusion.
- The JVM scheduler may ignore priority.
- Coarse grained.
- Difficult to enforce globally.
- Good - Implement a critical region using semaphores (or something).
- Done in the Runnable with complete control.
- Proper granularity.
- Enforcement meshed with access.
- Threads run asynchronously; their state is unknown.
- They may hold resources, be in a critical region.
- Disturbing a thread in a delicate state can lead to trouble.
-
t.suspend() suspends thread t's execution.
-
t may be in a critical region or hold locks.
-
t.resume() - continues t's execution.
- Both are depreciated; don't use them.
-
t.yield() - cede execution to some other thread.
- A hint only, the JVM may ignore it.
- Mostly useless; don't use it.
-
t.setPriority(p) sets thread t's priority to p.
- Another hint; may be ignored.
-
t.setPriority(Thread.MAX_PRIORITY) does not implement
atomicity.
- Mostly useless; don't use it.
-
t.sleep(n) suspends thread t's execution for at least n
milliseconds.
- The delay may be longer; milliseconds may differ.
- Thread status is tricky to deal with.
- Status notifications are asynchronous.
- Status is easily interfered with.
- Don't write code that depends on thread status.
- Concentrate instead on the task's status.
- Replace thread status with task synchronization.
- Example - waiting for n threads to terminate.
- Bad - waiting for each thread's termination status.
- Other threads may steal the status.
- Handling runaway threads difficult.
- Good - synchronizing on a shared counter.
- A specific class instance can't be intercepted.
- Alternate behaviors (e.g., timeouts) possible.
- Status is most useful when debugging.
-
Thread.currentThread() returns the calling thread.
-
t.join() blocks the calling thread until thread t terminates.
- There's no value passed between joining and joined thread.
-
t.isAlive() returns true iff thread t is alive.
- Mostly useless because it suffers from interference.
-
t.getName() returns thread t's print name.
- Set by
t.setName(String) or by a Thread constructor.
- Threads are virtual machines; Runnables are the programs they run.
- Understand and exploit the differences.
- Avoid subclassing Thread to eliminate Runnables.
- This confuses two concepts better kept separate.
- There's a small number of useful methods in Thread and Runnable.
-
start() will get you far.
- Understand why you shouldn't use various unsafe methods.
- If you don't understand, you'll make the same mistakes.
- Don't control threads, control tasks via Runnables.
- Greater control, and less contact with the weak JVM.
This page last modified on 11 July 2002.