"Imagine that you are using your favorite text editor on a large file. When it starts up, does it need to examine the entire file before it lets you edit? Does it need to make a copy of the whole file? Wouldn't it be nice for it to show you the first page, enabling you to begin editing, and somehow (in the background) complete the slower tasks necessary for initialization? Threads allow exactly this kind of within-the-program parallelism." from Java in 21 Days
A thread represents a single process in execution on a system. Threads are sometimes referred to as light-weight processes or execution contexts. Typically, each thread controls a single aspect within a program, such as monitoring a particular input device or handling all of the disk I/O.
Has an execution context, program counter, stack, ...
A single-threaded program uses only one thread to control its execution. Many
applications and applets are single-threaded.
If you see a browser page with two applets running at the same time, or
scrolled your page while the applet continued running, then the browser
is multithreaded.
Multithreaded applications (and applets) use several execution contexts to
accomplish their tasks. They make use of the fact that many tasks contain
separate and distinct sub-tasks. One thread can be used for each subtask.
A multithreaded program allows each thread to start and finish as quickly as
possible; this behavior provides better response to real-time input.
Note that the vonNeumann machines (machines with single processors) are becoming obsolete fast! Multiple
processor machines are here; threads are great
experience for parallel processing and parallel algorithm considerations which can be used on these multiple processor machines.
Here are a couple of examples of SUN using Threads for use in Swing:
Concurreny in Swing and Threads in Applets
A SimpleThread example:
Because applications go through main() when starting, this is a
natural place to create and start threads. Examples:
Because we have direct control of our thread, we must start it directly as
well:
t1.start();
Below is a first simple use of threads.
t should contain a valid thread of execution. We control this thread in the
run() method.
Once inside the run methood, you can execute statements as in any program.
run() serves as the main() routine for threads. When
run() finishes, so does the thread.
In these examples, we are pausing for a period of time (random (below) and 300
milliseconds (above))
sleep (300);
The sleep() method simply tells a thread to be quiet for (at least) the
specified number of milliseconds. You can use sleep when you delay execution
of a thread. The sleep() method does not take up system resources while the
thread sleeps. Other threads can (will) continue to work.
Below is a another simple introduction to threads.
import java.util.Random;
The other way to create a thread is to declare a class that implements the Runnable interface.
That class then
implements the run method. An instance of the class can then be allocated, passed as an argument when
creating Thread, and started.
The program below creates a thread that prints 3 messages.
Notice the interface Runnable (remember interface and
implement?)
To create a thread, you must subclass Thread so that it defines its
own run() method,
The interface specifies the run() method that is required for use with
the Thread class. Any class that implements this interface can
provide the "body" of a thread. By implementing the interface
Runnable you declare your intention to run on a separate thread.
Although SUN deprecated some thread methods, a user should be familiar with
what they were and why they were deprecated.
Pausing a thread
Often the ability to suspend a thread without a specific time limit is useful.
Suppose, for example, you are building an applet with an animation thread, you
might want to provide the user with the option to pause the animation until the
user wanted to resume.
You do not want to throw the animation away, you want to de-activate it. For
this type of thread control you can use
t1.suspend();
This method does not halt the execution permanently. The thread is suspended
indefinately until you activate the thread using
t1.resume();
A thread will automatically suspend() and then resume() when it's first blocked
at a synchronized point and then later unblocked (when it is that threads turn
to "run").
Stopping a thread
We can stop a thread with
t1.stop(); // stops the thread by throwing a ThreadDeath
error.
This does not destroy the thread, but it halts execution. When a thread is
stopped, the state of the thread object is set so that it is not restartable.
Execution cannot be restarted by using t1.start(). The
start() method won't return an exception condition, but the
run()
method also won't be called. The isAlive()method also won't return
true.
In the examples shown, we did not need to explicitly stop the threads. We
simply let them finish. A thread runs until the run() method returns or until
the stop() method of its Thread object is called. More complex threaded
examples will require control over each thread; the stop() method can be used
therein.
If needed, you can test to see if your thread is "alive". A thread is
alive if it has been started and has not been stopped.
t1.isAlive(); // returns true if t1 is alive
Why JavaSoft is Deprecating Thread.stop,
Thread.suspend and Thread.resume and also look at the deprecated methods in the thread API
Producers and Consumers
The idea is to design threads to use common objects, which each thread
can manipulate independently of the other threads.
The classic thread communication example builds on a producer/consumer model:
one thread produces some output; the other thread consumes (uses) whatever the
output is.
Monitors
Monitors are important pieces of multithreaded applications because they
keep the communications flowing.
Monitors will hold the shared information in a Shared Object and they usually
perform the function of monitoring information transactions between two (or
more) threads.
The data members in the Shared Object should be private to keep the Producer
and Consumer from getting at the data directly. why? how?
Because...
Synchronized access methods stop producers and consumers from corrupting
a shared object. While the producer is adding a data object to the Shared
Object, the consumer cannot be taking one, and vice versa. (critical
sections)
How does one add or use? The class that holds the data object has these
synchronized methods (of course).
The synchronized keyword tells Java to make the block of code in the
method thread safe. Only one thread can be allowed inside this method at once,
and others have to wait until the currently running thread is finished.
Obvious Note: this implies that synchronizing large, long-running methods is
almost always a bad idea.
This synchronization (remember semaphores?) is vital to maintaining the
integrity of any Shared Object. The notify() method at the end of
each access method signals any waiting process. The waiting process will try
its access again.
yield() makes the current thread give up control to any other threads
of equal priority that are waiting to run.
t1.getPriority()
t2.setPriority(int)
t2.setPriority(t1.getPriority() + 1)
Understanding Thread Priority a SUN tutorial, another
source
Typically the shared object should be a private instance variable.
Why private?
Why instance?
The private nature will keep the Producer and Consumer from getting the data
directly. Direct data access can cause trouble. If, for example, the consumer
tried to pull data out of an empty buffer, you would get unnecessary
exceptions, or you could lock up the process.
If the variable were a class variable, you could have multiple threads
modifying it by using different instances of the class.
Lab 2 uses threads and must use the producer, consumer, monitor pattern: Lab 2 and
examples
More on synchronization and why have threads coming.
Introducing Threads
SO, threads can be simple but also possibly dangerous.
First, let us look at the basics. There are two main techniques with which to
instantiate threads one uses inheritance and the other implements an Interface.
Then we will consider some of the problems.
The first line creates a new subclass of thread called T. In the
second, the two arguments passed to TestThread (see below) represent
the name of our thread and the time we want the thread to delay before printing
its message.
Manipulating Threads
While the main() method retrieves its arguments from the argv parameter (which is typically set from the command line), the newly created thread must receive its arguments programmatically from the originating thread.
Hence, parameters can be passed in via the constructor, static variables,
or any other technique designed by the developer
A simple multithread example to test the TestThread:
Runnable
See Thread API for constructors of Threads
OR
you must pass a Runnable object to the
Thread constructor.
from tutorial
History
Ahhhhhhh deprecated notes below!
Note deprecated methods in the thread API What happens when you try to restart a thread? The answer is that it
actually depends on when you restart it. When the stop() method is
called on a thread, it actually takes time for the thread to stop. Hence, what
happens when the start() method is called depends on a race condition.
Multi-Thread Communications
Priority: