Ask Questions?

View Latest Questions


 
 

Threads
Posted on: July 26, 2006 at 12:00 AM
Threads vs Processes

Threads

Basic Idea

  • Execute more than one piece of code at the "same time".
  • If more than one CPU, true concurrency is possible.
  • If only one CPU, use time slicing.
    • Rotates CPU among threads / processes.
    • Gives appearance of simutaneous execution.
    • Very advantageous in several situations.
    • Cost of switching is important.
    • Doesn't improve CPU-bound task.

Threads vs Processes

Multiple processes / tasks

  • Separate programs.
  • Separate address spaces.
  • High switching overhead
  • Costly interprocess communication.

Threads

  • Within one program.
  • Shared address space
    • May use same hardware cache
    • May use same virtual memory.
    • Shared heap.
    • Separate stack for each thread.
  • Lower switching overhead than processes.
  • Easy communication with other threads.

Cooperative vs Pre-emptive

Cooperative multithreading

  • A thread decides when to give up the CPU.
  • It can call yield() to temporarily give it up.
  • Older systems: Windows 3.1, Mac OS ?
  • One thread can hog the whole CPU.
  • More efficient for some applications because fewer switches. Solaris "green threads".

Pre-emptive

  • OS allocates time slice to a thread.
  • At the end of the time slice, or when blocked, other higher or equal priority threads are given a time-slice.
  • Used on most systems.

Operating system may choose

  • Hard to write really portable multi-threaded applications.

Example - Long action

Problem

The user presses a button on the GUI interface that starts a long action. The single GUI thread is now in use, so the GUI interface becomes completely unresponsive until the action is completed.

Solution

For long actions, start a separate thread so that the GUI thread may continue to operate the interface.

Example - Slow IO

Problem

IO is relatively slow. Let's say you're writing a browser. It reads a web page that has a lot of links to images. If you get the images sequentially, the program will spend most of its time waiting for network IO operations to complete.

Solution

Start a separate thread for each image that must be loaded. The IO wait time is therefore reduced to the longest wait, not the sum of all waits.

Example - Animation

Problem

You want to show an animated image, but also continue regular processing. Every so many milliseconds you need to draw a new image. How can you do this while you are doing some other computation?

Solution

Start a separate thread for the animation that starts up at regular intervals. The javax.swing.Timer class is a class that helps you do this.

Thread Life Cycle States

  • New - Created, but no one has requested it to start.
  • Ready - It's in a queue ready to run and is waiting for the CPU.
  • Running - It's currently running.
  • Waiting - It's waiting for something. When finished waiting, goes to ready queue.
    • Waiting. Someone needs to tell it to go (notify() / notifyAll())
    • Sleeping. Waiting for a time interval to expire.
    • Blocked by IO. Completion of IO will put it in the ready queue again.
    • Blocked by synchonization. Someone else has locked object that is needed.

Thread Life Cycle Transition State Diagram

[ INSERT DIAGRAM HERE ]

Thread Scheduling

  • Every thread has a priority.
  • The OS may not support this many levels.
  • The OS scheduler chooses highest priority Ready thread to run.
  • It's possible for low priority threads to "starve".

Thread class and Runnable Interface

  • Runnable
    • Must define the run() method.
    • Implement Runnable if you are only going to start() a tread.
  • Thread class
    • Implements Runnable, so must define run()
    • Has other methods.

Synchronization

  • Every object has a monitor.
  • Only one thread can lock an object's monitor at one time.
  • Calling a synchronized instance method locks that object's monitor.
    • Other calls block when they call that synchronized method.
    • When method returns, lock is freed.
    • Scheduler may then run one of the blocked threads.
  • Deadlocks are largely prevented, but will throw exception if detected.
  • Blocks may also be synchronized.

Data Structures and Synchronization

  • Before Java 1.2
    • All data structures synchronized, eg, Vector
    • There is overhead in entering synchronized methods.
  • Java 1.2 Collections
    • Newer data structures are NOT synchronized by default.
    • Can create a synchronized wrapper if needed.
  • Java 5
    • Some concurrent data structures are added. These are carefully coded so they may be used by more than one thread without synchronization and without producing bad results.
    • It can be difficult to verify that code can be executed concurrently.
    • Remember that each thread has its own stack.

Daemon Threads

  • Threads that are only uses for services should be marked as Daemon threads.
  • Example: A timer thread.
  • th.setDaemon(true);
  • If only daemon-threads remain, the program is terminated.

Thread Methods

  • Thread.currentThread() - Returns current thread.
  • Thread.sleep(millis) - Sleeps current thread # milliseconds.
  • th.start() - Starts thread th.
  • th.interrupt() - Interrupts th.
    • If th is blocked, th throws InterruptedException.
    • Otherwise a flag is set that must be tested by th.
  • th.isInterrupted() - True if interrupted. Eg,
    • if (Thread.currentThread().isInterrupted()) ...
  • th.join() - Waits for th to "die".
  • th.yield() - Voluntarily allows other threads to execute.

Thread Example

  • Create a thread. Do everything inside run() method.
    Thread busyBee = new Thread() {
        public void run() {
            doAllThatWork();
        }
    }
  • Start the thread where appropriate. The start() method creates a new call stack for this thread and then calls the run() method.
    busyBee.start();
  • If you call run() yourself, it will just run it in your thread.

Object Methods for Threads

  • obj.wait() - Current thread waits until object unlocked by notify() call.
  • obj.notify() - Awakens arbitrary thread "waiting" for this object. Can only be called if current thread owns the lock on this object (eg, in a synchronized method). Arbitrary thread is still blocked until current thread releases lock.
  • obj.notifyAll() - Awakens all threads "waiting" for this object..

Timers

  • javax.swing.Timer
  • java.util.Timer
  • [TODO: Insert example here]

GUI and Threads

  • New GUI event-dispatching thread started by setVisible().
  • Main thread can terminate after starting GUI.