thread

Document Sample
thread Powered By Docstoc
					                               java.notes
                                Threads

1. Threads: methods of class java.lang.Thread   :

Thread(Runnable target)
Thread(Runnable target, String name)
String getName()
void getName()
void setDaemon(boolean on)
void setPriority(int newPriority)
void start()
static void yield()
static void sleep(long millis) throws InterruptedException
static Thread currentThread()
void interrupt()
static boolean interrupted()
void join() throws InterruptedException

2. Synchronization
3. Monitors: Object methods:

void   wait() throws InterruptedException
void   wait(long millis) throws InterruptedException
void   notify()
void   notifyAll()

4. Threads and Swing: SwingUtilities methods:

static void invokeLater(Runnable r)
static void invokeAndWait(Runnable r) throws InterruptedException

5. SwingWorker

abstract Object construct()
void finished()
void interrupt()
Object get()

6. Timer

Timer(int millidelay, ActionListener listener)
void addActionListener(ActionListener listener)
void setRepeats(boolean flag)
void start()
void stop()
void restart()




                                   1
                                     Threads
   Multi-threaded programming is not for beginners. Stay away from
    concurrency until you gain enough skill and experience to become an
    intermediate programmer.
   If you are going use threads, buy the book:

Concurrent Programming in Java, Design Principles and Patterns, Doug Lea


                             Why create threads?
   If it's harder to code, test and reason about multithreading, why do it?
          o Responsiveness. No user wants to feel like their keyboard or the
             mouse is frozen! Rule: if it is going to take a long time (especially if we
             are talking about the EDT = Event Dispatch Thread), do it in another
             thread.
          o Cancellation. You can cancel an operation by interrupting the thread
             carrying it out.
          o Blocking operations. By default, reading from a socket blocks the
             thread when no data is available. If you don't want to slow down the
             rest of an application, dedicate a thread to read from a socket.
          o RMI. RMI makes your application multithreaded (because of the last
             point). Any remote object must be thread-safe, as should any code
             called directly or indirectly by a remote object.
          o Natural Architecture. Some designs decompose into largely
             independent tasks. Once you understand concurrency it is hard not to
             use threads in this case.

   For all those reasons, the majority of interesting Java programs will have
    multiple user threads. In fact, your java programs are already multithreaded!
    The garbage collector runs in its own thread (where did you think it was
    hiding?), Swing uses the EDT (Event Dispatch Thread) for processing events,
    and asynchronous Image loading is done in special "Image Fetcher" threads.

    interface java.lang.Runnable
    public interface Runnable
    {        public void run();
    }

    The run method of a runnable object is the "main" method for a thread; when
    the thread starts it is executed; when it finishes, the thread terminates.




                                            2
    class java.lang.Thread

   How to launch a thread:

    Runnable runner = new YourRunnable();
    Thread t = new Thread(runner, "my thread"); //name is optional
    t.start();
    //the JVM calls the run() method of the thread.
    //The result is that two threads are running concurrently

    Two Thread constructors:

    Thread(Runnable r)   //or
    Thread(Runnable r, String name)

    You can achieve a similar result by subclassing Thread, but the approach
    here is better. By the way, the name property is used to informally identify
    threads, mainly for debugging:

    String getName()
    void setName(String newName)

   Two properties you can set before invoking start():

    void setDaemon(boolean on)
    void setPriority(int newPriority)

    If only daemon threads are alive, the JVM will terminate. Often helper threads
    (like timers) are daemons.

    Threads with higher priority are executed in preference to threads with lower
    priority, but the operating system has the final say for CPU scheduling.
    Priorities range from 1 to 10; Thread defines the constants:
    MIN_PRIORITY              1
    NORM_PRIORITY             5
    MAX_PRIORITY              10

    Doug Lea gives these task categories for priority settings.
    Crisis management            10
    Interactive, event-driven    7-9
    IO-bound                     4-6
    Background computation       2-3
    Run only if nothing else can 1




                                         3
    Example: launching a background daemon:

    Thread t = new Thread(new MyDaemon(), "my daemon");
    t.setPriority(3);
    t.setDaemon(true);
    t.start();

   Sometimes a thread is a CPU-hog (You may notice that the GUI moves
    jerkily). This could be caused by CPU-bound number crunching. To try to
    share the CPU among other threads of the same priority, occasionally call the
    following method from your CPU-hog thread:

    static void yield()


    This causes the currently executing thread object to temporarily pause and
    allow other threads to execute. Don't worry about this to begin with!

   You can cause the current thread to pause by calling sleep(), and you can
    rudely wake up a blocked thread by sending it the interrupt() message.

    static void sleep(long millis) throws InterruptedException
    void interrupt()



   join() causes the current thread to block until the thread object that is the
    target of the join() invocation terminates. Since this blocks the current thread,
    it can be interrupted.

    void join() throws InterruptedException

    Example: launch a thread then, for no good reason, wait for it to terminate!

    Thread t = new Thread(new MyRunner(). "my runner");
    t.start();
    t.join();
    //next lines executed after t terminates




                                          4
                               Synchronization
   Threads represent largely independent tasks. What is dependency?
    Sometimes there are order constraints: you can't read a file before it exists.
    More often, dependency arises when multiple threads access the same data
    (object). Care must be taken with this access – the timing involved is
    unknown: one thread may read data when another thread is only half-way
    through a complex update of the data.

In the following example, two threads are accessing the same integer, initially 0.
They both increment it 100 times, so the final value should be 200. Is it?

public class SyncTest
{     public static void main(String[] argv)
      {     SharedInt shared = new SharedInt();
            Thread bee = new Thread(new Busy(shared));
            Busy cee = new Busy(shared);
            bee.start();      //returns immediately
            cee.run();        //simple subroutine
            try {bee.join();}
            catch (InterruptedException e) {e.printStackTrace();}
            System.out.println("final val= " + shared.getVal());
      }
}

class Busy implements Runnable
{     public Busy(SharedInt s) {m_shared = s;}
      public void run()
      {     for (int i=0; i<100; i++)
            {     m_shared.increment();
            }
      }
      private SharedInt m_shared;
}

class SharedInt
{     public int getVal() {return m_val;}
      public void increment()
      {     int temp = m_val+1;
            try
        {   Thread.sleep(10);
            }
            catch(InterruptedException exc)
            {     exc.printStackTrace();
            }
            m_val = temp;
   }

    private int m_val;
}




                                         5
Java offers a simple mechanism for controlling object access: synchronized
blocks and the special case of synchronized methods.

   Syntax:

        public synchronized void f() {. . .}

        public void f()
        {     synchronized(obj) { . . .}
        }

       Meaning: every object has a lock. A lock is held by at most one thread. To
        enter a synchronized block, a thread must first acquire the lock for the
        object. If the lock is held by a different thread, the first thread blocks until
        the lock is no longer held and it is able to acquire the lock itself.

       Overloading and the synchronized keyword. When overloading a method,
        you can add or remove this modifier. Abstract methods cannot be modified
        with synchronized.

       Constructors cannot be written:

        public synchronized X() { . . .}

    But they can contain synchronized blocks. They rarely need to worry about
    synchronization: finish constructing before letting another thread to see an
    object!

       Static methods can be synchronized. What object do they use for locking?

       Thread-safe: a class is thread-safe or multithreading-safe if concurrent
        access by arbitrary threads cannot leave instances of the class in an
        inconsistent state. If you want to reuse a class in arbitrary situations, it
        may be necessary to ensure it is thread-safe. On the other hand, an object
        could be used in a restricted context that limits thread access. This is a
        tricky problem, and one reason why Doug Lea wrote his book!

       A simplistic approach is to define a fully-synchronized object: make every
        method (except the constructor) synchronized. This makes the object
        thread-safe but it may also restrict liveness so far as to introduce
        deadlock!

       Remember the simple rules of thumb:
          o Lock before you read
          o Lock before you write
          o Never lock when invoking methods on other objects.



                                            6
Classic example: listener notification
public interface SomeListener
{     public void update(SomeEvent event);
}

public class SomeSubject
{     private ArrayList m_l = new ArrayList();//serial immutable

      public synchronized void AddListener(Listener l)
      {     ArrayList ll = (ArrayList) m_l.clone();
            ll.add(l);
            m_l = ll;
      }

      public synchronized void removeListener(Listener l)
      {     ArrayList ll = (ArrayList) m_l.clone();
            ll.remove(l);
            m_l = ll;
      }

      protected void fire(SomeEvent evt)
      {     ArrayList ll;
            synchronized(this)
            {     ll = m_l;
            }
            for(int j=0; j < ll.size(); ++j)
                  ((SomeListener)ll.get(j)).update(evt);
      }
      . . .
}

Why would it be a bad idea to simple make fire a synchronized method?




                                      7
                                    Monitors
      Synchronization often isn't enough to manage threads access to shared
       objects. For example, suppose a thread is dedicated to delivering events
       put into a queue by other threads. What should it do when the queue is
       empty? Wait. What should threads that enqueue events do? Notify the
       delivery thread that it can stop waiting. This is exactly what the following
       Object methods do.

   void   wait() throws InterruptedException
   void   wait(long timeout) throws InterruptedException
   void   notify()
   void   notifyAll()



   public final class Subject
   { public Subject()
      {     new Thread(m_runner).start();
      }

       public synchronized enqueue(Event evt)
       {     m_queue.addList(evt);
             notify();
       }

       private synchronized Event dequeue() //called by runner
       {     while (m_queue.isEmpty())
                   wait();
             return (Event) m_queue.removeFirst();
       }

       private LinkedList m_queue = new LinkedList();

       private Runnable m_runner = new Runnable()
       {     public void run()
             {     while(true)
                   {     Event evt = dequeue();
                         <<do something with event>>
                   }
             }
       }
   }


Be careful: classes that launch threads in their constructors can be problematic
to derive from. That is why I made this class final.




                                         8
InterruptedException
InterruptedException is a checked exception that is thrown when a thread is
waiting, sleeping etc… and another thread invokes Thread method interrupt():

public class Interruptor
{     public static void main(String[] argv) throws Exception
      {     JFrame f = new JFrame("interrupt");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            new Interruptor(f.getContentPane());
            f.pack();
            f.show();
      }

      public Interruptor(Container cp)
      {     JButton b = new JButton("interrupt");
            cp.add(b);
            b.addActionListener(new ActionListener()
            {     public void actionPerformed(ActionEvent evt)
                  {      m_t.interrupt();
                  }
            });
            m_t.start();
      }

      private BufferedReader m_r = new BufferedReader(
            new InputStreamReader(System.in));

      private Thread m_t = new Thread()
      {     public void run()
            {     while (true)
                  {     try
                        {      sleep(100000);
                        }
                        catch(InterruptedException e)
                        {      System.out.println("INTERRUPT");
                        }
                        //allows you to press button before sleeping:
                        System.out.print("enter a line of text\n>");
                        try {m_r.readLine();} catch(IOException e) {}
                        System.out.println("1 line read");
                  }
            }
      };
}

A tidy death. How should your code respond to an InterruptedException?
Thread interrupts typically serve as requests that activities be cancelled. Nothing
stops you from using interrupts for other purposes, but this is the intended
convention. In almost all circumstances, canceling the activity associated with a
thread should cause the thread to terminate. But there is nothing about interrupt()
that forces immediate termination. This gives an interrupted thread a chance to
clean up before dying.


                                        9
The following methods all throw InterruptedException. If code that may be
interrupted doesn’t call these methods at regular intervals, you should explicitly
check the interrupted status flag.

class Object:
void wait() throws I.E.
void wait(long millis) throws I.E.

class Thread:
static void sleep(long millis) throws I.E.
void join() throws I.E.
void join(long millis) throws I.E.

class MediaTracker:
void waitForID(int id) throws I.E.

class ReferenceQueue:
Reference remove() throws I.E.

class SwingUtilities:
static void invokeAndWait(Runnable doRun) throws I.E.,
            InvocationTargetException

   o.wait() blocks until another thread invokes o.notify(), o.notifyAll()
   The timeout version wait(millis) returns normally if the specified time elapses.
    There is no intrinsic way to distinguish this from notify(). But see the code on
    the nest page for a programmed solution.
   t.join() blocks until thread t terminates.
   The timed version t.join(millis) returns normally if the specified time elapses.

The following Thread methods are all about interrupting:
void interrupt()
static boolean interrupted()
boolean isInterrupted()

   Every thread has a flag indicating its interrupted status.
   If a thread has its interrupted status flag set, then methods like wait() and
    sleep() immediately throw InterruptedException. The interrupted status of the
    current thread is cleared by these methods before this exception is thrown.
   Method t.isInterrupted() returns t's interrupted status.
   Static method Thread.interrupted() returns the current thread's interrupted
    status while simultaneously resetting it. Since this method is static, one thread
    can't reset another status, which makes sense.
   If a thread wants to invoke a non-static method like interrupt() on itself, use
    the static method currentThread():

static Thread currentThread()

Thread.currentThread().interrupt();              //set your own flag




                                         10
                  Example: A better synchronized?

Synchronized blocks are a good idea, but does a thread really want to block for
an arbitrarily long amount of time? Sometimes it would be nice if attempts to
synchronize would fail if time ran out. Exercise: come up with such a solution.

public class TimeoutLock
{     //if method times out, it throws IE as well
      public synchronized void acquire(long timeout) throws
InterruptedException
      {     if (timeout <= 0)
                  throw new IllegalArgumentException();
            long deadline = System.currentTimeMillis() + timeout;
            while (m_locked && timeout > 0)
            {     wait(timeout);
                  timeout = deadline - System.currentTimeMillis();
            }
            if (m_locked)
            {     throw new InterruptedException("Timeout");
            }
            m_locked = true;
      }

      public synchronized void release()
      {     m_locked = false;
            notify();
      }

      private boolean m_locked = false;

      public static void main(String[] args) throws Exception
      {     final TimeoutLock lock = new TimeoutLock();
            class R implements Runnable
            {     public void run()
                  {     try
                        {
                        while(true)
                        {     lock.acquire(1000);
                              Thread.sleep((long)(Math.random()*1100));
                              lock.release();
                              Thread.sleep((long)(Math.random()*100));
                        }
                        }
                        catch(InterruptedException exc)
                        {     exc.printStackTrace();
                              System.exit(0);
                        }
                  }
            }
            new Thread(new R(), "fred").start();
            new Thread(new R(), "barney").start();
      }
}




                                       11
                      Deprecated Thread methods
The following Thread methods are deprecated. Do not use them

void stop()          //Forces the thread to stop executing.
void suspend()       //Suspends this thread.
void resume()        //Resumes a suspended thread.

Why is stop() deprecated? The API documentation states:

Deprecated. This method is inherently unsafe. Stopping a thread with
Thread.stop causes it to unlock all of the monitors that it has locked (as a natural
consequence of the unchecked ThreadDeath exception propagating up the stack).
If any of the objects previously protected by these monitors were in an
inconsistent state, the damaged objects become visible to other threads,
potentially resulting in arbitrary behavior. Many uses of stop should be replaced
by code that simply modifies some variable to indicate that the target thread
should stop running. The target thread should check this variable regularly, and
return from its run method in an orderly fashion if the variable indicates that it is
to stop running. If the target thread waits for long periods (on a condition variable,
for example), the interrupt method should be used to interrupt the wait.

Why is suspend() deprecated? The API documentation states:

Deprecated. This method has been deprecated, as it is inherently deadlock-
prone. If the target thread holds a lock on the monitor protecting a critical system
resource when it is suspended, no thread can access this resource until the
target thread is resumed. If the thread that would resume the target thread
attempts to lock this monitor prior to calling resume, deadlock results. Such
deadlocks typically manifest themselves as "frozen" processes.

Exercise: Rewrite Ex2.java to avoid using suspend() and resume().




                                         12
                            Threads and Swing
The Java2 GUI toolkit (Swing) is not thread-safe. Once a component is visible
most of its methods can only safely be called from the event dispatching thread
[EDT].

      There are a few methods that are always guaranteed to be thread-safe:
          o repaint(…)
          o addXYXListener() and removeXYZListener()
          o invalidate() and revalidate()
      Some components have specific methods whose contracts state that they
       are thread-safe. For example, subclasses of JTextComponent have the
       guarantee that setText() is thread-safe, and for JTextArea, append() is
       also thread-safe. (Note that JLabel's setText() carries no such guarantee.)
      How could you change a label's text from another thread: a thread has just
       read from a socket's input stream and wants to set a label's text – who yah
       gonna call? SwingUtilities.invokeLater:

//inner class where BufferedReader m_in is from a socket, perhaps. . .
private class HeyMabel implements Runnable
{     public void run()
      {     try
            {     String line = m_in.readLine();
                  setThelabel(m_lbl, line);
            }
            catch(IOException e) {}
      }
}

//helper method
private static void setTheLabel(final JLabel lbl, final String text)
{     SwingUtilities.invokeLater(new Runnable()
      {     public run()
            {     lbl.setText(text);
            }
      });
}

SwingUtilties has two static methods that allow you to execute code in the EDT:

void invokeLater(Runnable r)
void invokeAndWait(Runnable r) throws InterruptedException,
      InvocationTargetException

      InvocationTargetException     wraps any uncaught exception thrown in the
       execution of r (call method getTargetException() to extract it)
      Method invokeLater() is usually preferred over the blocking
       invokeAndWait() – why limit concurrency if you don’t have to?



                                       13
      To check if code is executing in the EDT (usually done for error checking)
       use the static SwingUtilities method:

boolean isEventDispatchThread()

      So what code is executed in the EDT? Your listeners' event handlers
       (like actionPerformed()). This turns out to be where most code that
       manipulates GUI components resides, so there is no need to worry about
       thread safety there:

private class BlackLabel implements ActionListener
{     public actionPerformed(ActionEvent evt)
      {     m_lbl.setText(evt.getActionCommand());
      }
}

      Of course, the previous comment assumes you don't maliciously call event
       handlers from other threads!




                                    SwingWorker
     Class SwingWorker provides a simple template for doing background
computation. Do the following:

   1. Subclass SwingWorker and override construct() to do background work.
   2. Optionally override finished() to do one final action. It will be executed in
      the EDT, executed whether or not the SwingWorker is interrupted.
   3. Other threads can call interrupt() to cancel the worker thread.
   4. Other threads can call get() to find the result. This method will block if the
      worker thread is not done yet.

abstract Object construct()
void finished()
void interrupt()
Object get()




                                         14
import javax.swing.SwingUtilities;

public abstract class SwingWorker
{     private Object value;
      private Thread thread;

      private static class ThreadVar
      {     private Thread thread;
            ThreadVar(Thread t)             { thread = t; }
            synchronized Thread get()       { return thread; }
            synchronized void clear()       { thread = null; }
      }

      private ThreadVar threadVar;

      protected synchronized Object getValue()
      {     return value;
      }

      private synchronized void setValue(Object x)
      {     value = x;
      }

      public abstract Object construct();

      public void finished() {}

      public void interrupt()
      {     Thread t = threadVar.get();
            if (t != null)
                  t.interrupt();
            threadVar.clear();
      }

      public Object get()
      {     while (true)
            {     Thread t = threadVar.get();
                  if (t == null)
                         return getValue();
                  try
                  {      t.join();
                  }
                  catch (InterruptedException e)
                  {      Thread.currentThread().interrupt(); //propagate
                         return null;
                  }
            }
      }




                                     15
    public SwingWorker()
    {     this(Thread.NORM_PRIORITY);
    }

    public SwingWorker(int priority)
    {     final Runnable doFinished = new Runnable()
          {     public void run() { finished(); }
          };

          Runnable doConstruct = new Runnable()
          {     public void run()
                {     try
                      {     setValue(construct());
                      }
                      finally
                      {     threadVar.clear();
                      }
                      SwingUtilities.invokeLater(doFinished);
                }
          };

          Thread t = new Thread(doConstruct);
          t.setPriority(priority);
          threadVar = new ThreadVar(t);
    }

    public void start()
    {     Thread t = threadVar.get();
          if (t != null)
                t.start();
    }
}




                                16
javax.swing.Timer

  Timer manages a thread for you. You just provide the code you want
  executed once, or repeatedly. Without Timer, you would have to use a Thread
  to control this, but Timer makes such code a snap to write.

  Timer(int millidelay, ActionListener listener)
  void addActionListener(ActionListener listener)
  void setRepeats(boolean flag)
  void start()
  void stop()
  void restart()

     The listener passed to the constructor can be null.
     The Timer doesn't start ticking until you call start()
     The listener will have its actionPerformed() method called every time the
      Timer "ticks"
     To only has the timer tick once, set the repeats property to false.
     This will be done in the EDT, so that your listener's code is free to access
      the GUI.




                                       17

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:20
posted:8/22/2011
language:English
pages:17