Threads

Synchronization:

   Threads are seperate flows of execution happening simultaneously. One use of threads is for aysnchronious communication. Some I/O methods like read() block waiting for input. A thread can listen on a socket for data while a seperate thread does the business of the rest of the application.

   When two threads are going to set/check the same data a "race condition" exists. Either thread may win the "race". One thread may be changing the data while the second is trying to get it. The "synchronized" keyword marks a method or a block of code as being executable by only one thread at a time. This is done through the use of the Object classes synchronization locking flag. When a thread wishes to execute a synchronized method or block it tries to obtain the lock for that object. If the lock is not available it waits for it.
You can mark methods as synchronized:
public synchronized void myMethod()
or blocks of code and specify the object to synch on:
synchronized (oneAtATimeObject)
{ -- synchronized code -- }



   The "wait()" and "notify()" allow threads to communicate. Both of these keywords must appear in synchronized methods or blocks. When a thread acquires a lock on a object but decides based on some condition that it should not run just yet it can call the "wait()" method. This temporaily release the lock on the Object and causes the thread to wait . Other threads can then obtain the lock, and execute the synched logic. If another thread calls the notify() method on the synched Object the first thread wakes up, re-aquires the lock and runs.

Priority:

   A thread defaults to the priority of the Thread that created it (normally 5 or NORM_PRIORITY). The Java VM runs higher priority threads before lower priority threads. The higher priority thread gets all the CPU cycles. The lower threads are not run at all until the higher thread completes by returning from run(). If the higher thread sleeps or is suspended- other threads will have a chance. A call to the "yield()" method will cause the VM to decide which thread to run. If there is another thread of *equal* priority then it may be selected to run next. Otherwise the highest priority thread will be seleceted to run next- even if it is the same thread that just called "yield()". "getPriority()" and "setPriority()" get and set the priority of a thread.

   The join() method causes a thread to wait for the specified thread to complete. This "joins" the threads back together into a single flow. For instance, the following code instantiates a new Thread and then waits for it to end before continuing on.
Thread t1 = new Thread();
t1.start();
t1.join();

Misc:

The "suspend()" and "resume()" methods can be used to pause threads.

The "currentThread()" method returns the currently executing thread.

The "isAlive()" returns a boolean about the state of the thread.

The "setName()" and "getName()" allow you to give threads meaningfull name tags.

NORM_PRIORITY, MAX_PRIORITY, and MIN_PRIORITY are Thread static final constants.
Normal is 5, Max is 10 (6 if an applet), and the MIN is 1

The "setDaemon()" and "isDaemon()" allow you to mark your thread as being a Daemon thread. A application will run until all the user threads are completed or otherwise terminated, VM threads like the garbage collector will die automatically. The setDaemon method marks the thread as a daemon which means it should exit once the user threads are done. For example; in a application the main thread can start up a thread to monitor a port. When main decides it is time to end the app it would have to explictly terminate the port thread, otherwise the app would continue running even though we had reached the end of the main() method. Marking the port thread as daemon will cause it end when main does. You can only call setDaemon() after the thread has been created but before you call start() on it.

Thread Synchronzation


import java.util.*;
import java.io.*;

class TestThreadSynch 
{
  public static void main(String [] args )
    {
      TestThreadSynch t = new TestThreadSynch();
      t.doIt();
    }

  public void doIt() 
    {
     //All our prints to standard out(screen) will be done through this object so that we can force
     // synchronization problems
     OurScreenPrinter osp = new OurScreenPrinter();
                             
     MyThread t1 = new MyThread(10,10,osp, "Thread 1");
     t1.start();
     if (t1.isAlive()) System.out.println(t1.filler + "Thread 1 is alive");
     else System.out.println(t1.filler +"Thread is not Alive");
     MyThread t2 = new MyThread(10,300,osp, "Thread 2");
     t2.start();
     MyThread t3 = new MyThread(10,600,osp, "Thread 3");
     t3.start();

     try { t1.join(); } catch (InterruptedException e) { System.out.println(e.getMessage()); }
     System.out.println( t1.filler + "Thread t1 is all done"); 
     if (t1.isAlive()) System.out.println(t1.filler + "Thread 1 is alive");
     else System.out.println(t1.filler +"Thread is not Alive");
     try { t2.join(); } catch (InterruptedException e) { System.out.println(e.getMessage()); }
     System.out.println(t2.filler + "Thread t2 is all done"); 
     System.out.println(t3.filler + "Suspending t3 for 2 seconds"); 
     t3.suspend();
     try { Thread.sleep(2000); } catch (InterruptedException e) { System.out.println(e.getMessage());  };
     t3.resume();
     try { t3.join(); } catch (InterruptedException e) { System.out.println(e.getMessage()); }
     System.out.println(t3.filler + "Thread t3 is all done"); 

    }

}



******************************************************************************************************

import java.io.*;

class MyThread extends Thread
 {
  static String spacerString ="";
  public String filler;
  int sackTime;
  int iterations;
  OurScreenPrinter osp;

   public MyThread(int iterationsIn, int sackTimeIn, OurScreenPrinter ospIn, String ThreadNameIn)
    {
      sackTime = sackTimeIn;
      osp = ospIn;                 //This is the Object that will need to be Synched
      iterations = iterationsIn;

      this.setName(ThreadNameIn);
      filler= spacerString;
      spacerString = spacerString + "                         ";
    }

  public  void run()
    {
     for (int k=0; k < iterations; k++) 
       { 
	try { Thread.sleep(sackTime); } catch (InterruptedException e) { System.out.println(e.getMessage());  };
        String outputString = filler + Thread.currentThread().getName() + " Iteration = " + Integer.toString(k);
        osp.print(outputString);  //This is the object/method that will need to be synched
       }
    } 

 } 

******************************************************************************************************

class OurScreenPrinter
 {
   StringBuffer holdString = new StringBuffer("");

   //public void print(String stringToPrintIn)
   public synchronized void print(String stringToPrintIn)
    {
     //Set the String to Print.
     holdString.setLength(0);
     holdString.append(stringToPrintIn);

     //Sleep for 1/10 second.  The holdString buffer is vulnerable to be changed and changed again by multiple threads
     //during this time.   
     try { Thread.sleep(100); } catch (InterruptedException e) { System.out.println(e.getMessage()); } 
     
     //Now Print it
     System.out.println(holdString.toString());  

     }
 } 

Output:
java TestThreadSynch

Thread 1 is alive
Thread 1 Iteration = 0
Thread 1 Iteration = 1
Thread 1 Iteration = 2
                         Thread 2 Iteration = 0
Thread 1 Iteration = 3
                                                  Thread 3 Iteration = 0
Thread 1 Iteration = 4
                         Thread 2 Iteration = 1
Thread 1 Iteration = 5
Thread 1 Iteration = 6
Thread 1 Iteration = 7
                         Thread 2 Iteration = 2
                                                  Thread 3 Iteration = 1
Thread 1 Iteration = 8
Thread 1 Iteration = 9
Thread t1 is all done
Thread is not Alive
                         Thread 2 Iteration = 3
                                                  Thread 3 Iteration = 2
                         Thread 2 Iteration = 4
                         Thread 2 Iteration = 5
                                                  Thread 3 Iteration = 3
                         Thread 2 Iteration = 6
                         Thread 2 Iteration = 7
                                                  Thread 3 Iteration = 4
                         Thread 2 Iteration = 8
                                                  Thread 3 Iteration = 5
                         Thread 2 Iteration = 9
                         Thread t2 is all done
                                                  Suspending t3 for 2 seconds
                                                  Thread 3 Iteration = 6
                                                  Thread 3 Iteration = 7
                                                  Thread 3 Iteration = 8
                                                  Thread 3 Iteration = 9
                                                  Thread t3 is all done



Thread Priority

import java.util.*;

class TestThreadPriority 
{
  public static void main(String [] args )
    {
      TestThreadPriority t = new TestThreadPriority();
      t.doIt();
    }

  public void doIt() 
    {
     MyThread t1 = new MyThread("Thread One: ");
     t1.setPriority(t1.getPriority() -1);  //Default Priority is 5
     t1.start();
     MyThread t2 = new MyThread("Thread Two: ");
     t2.setPriority(t2.getPriority() -2);
     t2.start();
     MyThread t3 = new MyThread("Thread Three: ");
     t3.setPriority(t3.getPriority() -3);
     t3.start();

     //Uncomment the 2 lines below and "Thread Three" will run before "Thread two" 
     //try { t1.join(); } catch (InterruptedException e) { System.out.println(e.getMessage()); } 
     //t3.setPriority(t3.getPriority() + 3);
    }
}

******************************************************************************************
import java.io.*;

class MyThread extends Thread   //If you implement Runnable instead; some methods like join() aren't available
 {
  static String spacerString ="";
  public String filler;

   public MyThread(String ThreadNameIn)
    {
      filler = spacerString;
      spacerString = spacerString + "                                ";
      setName(ThreadNameIn); 
    }

  public  void run()
    {
     for (int k=0; k < 5; k++) 
       { 
        System.out.println(filler + Thread.currentThread().getName() + " Iteration = " + Integer.toString(k) ) ;
       }
    } 

 }

*****************************************************************************************************
Output:
java TestThreadPriority

Thread One:  Iteration = 0
Thread One:  Iteration = 1
Thread One:  Iteration = 2
Thread One:  Iteration = 3
Thread One:  Iteration = 4
                                Thread Two:  Iteration = 0
                                Thread Two:  Iteration = 1
                                Thread Two:  Iteration = 2
                                Thread Two:  Iteration = 3
                                Thread Two:  Iteration = 4
                                                                Thread Three:  Iteration = 0
                                                                Thread Three:  Iteration = 1
                                                                Thread Three:  Iteration = 2
                                                                Thread Three:  Iteration = 3
                                                                Thread Three:  Iteration = 4