Java Threads

A thread allow us to run task simultaneously. In this post you will learn how to initialize a thread, what is Runnable interface and Thread class, when we use Runnable or Thread classes, running multiple threads, thread synchronization.

A thread begins as an instance of java.lang.Thread. To create, start and pause threads you should at least know following methods.

  • start()
  • yield()
  • sleep()
  • run()

You want to do some job with a thread, the job first starts in run() method.

public void run(){
//your job code goes here
}

You can construct a thread in two ways.

  • Extend java.lang.Thread
  • Implement Runnable interface

So why you cannot just use extending Thread ? Because Java does not support multiple inheritance, for example you have a window which extends JFrame and you want to run a job at background while displaying window. Yes you should use thread in this situation but it is illages in Java to say MyClass extends JFrame,Thread so you should use MyClass extends JFrame implements Runnable

Extending Thread is not a good design behaviour, if you implement Runnable instead of Thread, you could add a parent class in the future but if you extends Thread, you dont have a chance to add a parent class for further design decisions.

Extending java.lang.Thread

class MyClass extends Thread {
  public void run(){
    System.out.println("My thread code...");
  }
}

Implementing java.lang.Runnable

class MyClass implement Runnable {
  public void run(){
    System.out.println("Thread code goes here");
  }
}

Initializing a Thread

Always a thread execution begins as an instance of a Thread class. Whether you extend Thread or implement Runnable you always need Thread object.

If you extend Thread class initialization is simple

MyThreadClass t = new MyThreadClass();

If you implement Runnable first you should initiate your Runnable class then you should pass it to a thread object as a parameter.

RunnableClass r = new RunnableClass();
Thread t = new Thread(r);

If you create Thread object with no argument, object runs its own run() method. If you pass a Runnable as a parameter it runs passed run() method. You could also use one Runnable object for more than one thread object. In this situation all threads runs same run() method.

class ThreadClass {
  public static void main(String[] args){
    RunnableClass r = new RunnableClass();
    Thread t1 = new Thread(r);
    Thread t2 = new Thread(r);
  }
}

Until this point, we have learnt how to create Thread object, so how can we start a thread.
You could simply start a thread by calling t.start() and thread’s state changes “new” to “runnable” and target run() method is executed.

Runnin Multiple Threads

In this part we will run multiple threads with same target run() method. Here we go.

First I will create a class which implements Runnable interface.

public class MyRunnable implements Runnable {
	@Override
	public void run() {
		for(int i =0; i < 3; i++){
			System.out.println("Name: " + Thread.currentThread().getName() + " i: " +i);
		}
	}
}

So, now I will create a class which contains main method and starts threads.

public class MultipleThreads {
	public static void main(String[] args) {
		MyRunnable myRunnable = new MyRunnable();
		Thread t1 = new Thread(myRunnable);
		Thread t2 = new Thread(myRunnable);
		Thread t3 = new Thread(myRunnable);
 
		t1.setName("Malkara");
		t2.setName("Kesan");
		t3.setName("Tekirdag");
 
		t1.start();
		t2.start();
		t3.start();
	}
}

This program may produce following results. I said “may produce” because there is no specific order among threads execution.

Example Result -1
Name: Malkara i: 0
Name: Kesan i: 0
Name: Kesan i: 1
Name: Kesan i: 2
Name: Tekirdag i: 0
Name: Malkara i: 1
Name: Malkara i: 2
Name: Tekirdag i: 1
Name: Tekirdag i: 2

Example Result -1
Name: Kesan i: 0
Name: Kesan i: 1
Name: Kesan i: 2
Name: Malkara i: 0
Name: Malkara i: 1
Name: Malkara i: 2
Name: Tekirdag i: 0
Name: Tekirdag i: 1
Name: Tekirdag i: 2

There is another interesting point is, threads’ starting order and execution order may differ.
So there is some key points which we should not forget.

  • Thread execution order is controlled by scheduler.
  • We cannot control scheduler.
  • It is not guaranteed that, how many times a thread will run and how long every run will take.
  • You should always remember that, a group of thread execution will start and end but you can not control internal scenario.

But you can make some small arrangement over thread execution scenarios. If want to say, run a thread after another thread execution ended, you could use join.

When a thread’s run() method completes its execution, we can say that, thread is dead. Actually thread is not dead, if you have reference to that thread object, you can call all Thread class methods on that object except start(). It means that if a thread’s run() method completes its execution, you cannot start that thread again. If you call start() method twice, IllegalThreadStateException is thrown.

So, until here we have seen three thread states, new, runnable and dead.

Thread Scheduler

Thread schedular is a part of JVM, thread schedular decides which thread should run in a give moment. In a single processor environment only one thread run at a time, but scheduler switches between threads and execution seems simultaneous.

Althought we cannot control thread schedular, we can affect it partially. There are some methods to help us to affect schedular.

public static void sleep(long millis) throws Inte
public static void yield()
public final void join() throws InterruptedExcep
public final void setPriority(int newPriority)

Thread related methods from java.lang.Object

public final void wait() throws
public final void notify()
public final void notifyAll()

Threads could be in one of the following five states.

  • New – This state is between, thread object creation and calling start() method
  • Runnable – This state is, when thread is ready to run but not running. At this moment thread is wait in thread pool to be selected by thread schedular.
  • Running – Thread really does some job in this state. Thread switches between Runnable and Running states.
  • Waitin, blocked, sleeping – This state is similar to Runnable but, this time thread waits for an event occur to switch Running state. (May be waiting for an I/O operation to finish)
  • Dead – If thread’s run method completes, it means it is in Dead state. Thread instance is still valid in Dead state you can call instance methods but absolutely thread execution is ended.

Blocking Thread Execution

Followings are some thread blocked reasons

  • Sleeping
  • Waiting
  • Object Lock

Sleep

sleep() method is a Thread class’ static method. It pauses thread execution for a given time. run() methods generally contains an infinite loop. You can tell a thread to do some job regularly in specific time slices by using sleep() method.

try{
  while(true){
    Thread.sleep(24*60*60); // one day
    ringRing();
  }
}
catch(InterruptedException e){}

If you run this program 7:00 AM, it will wake you up in every morning 7:00 AM.
And it is important : When thread sleep time ended, it does not mean thread immediately goes to running state. It goes from sleeping state to runnable state. If thread scheduler selects that thread to run, then thread goes to running state.

Here is some code which prints country names in every three seconds.

public class ThreadSleep{
  public static void main(String[] args){
   String[] countryNames = {"Turkey","USA","UK","France","Spain"};
   try{
    for(String s : countryNames){
      System.out.println(s);
      Thread.sleep(3000); // 3 seconds (3000 millis)
    }
   }
   catch(InterruptedException e){}
  }
}

Thread Priorities and yield()

Usually threads have priorities between 1 and 10. Highest valued thread is usually selected from thread pool to run.

Thread’s Priority

public class PriorityRunnable implements Runnable {
	@Override
	public void run() {
		for(int i = 0; i < 100;i ++){
			System.out.println(Thread.currentThread().getName() + ": " +i);
		}
	}
 
}

Main method

public class ThreadPriority {
	public static void main(String[] args) {
		Thread t1 = new Thread(new PriorityRunnable(),"t1");
		Thread t2 = new Thread(new PriorityRunnable(),"t2");
		t1.setPriority(3);
		t2.setPriority(5);
		t1.start();
		t2.start();
	}
}

I got below result after running ThreadPriority class.

t2: 0
t2: 1
t2: 2
...
..
.
t2: 90
t2: 91
t2: 92
t2: 93
t2: 94
t1: 0 -> There is a chance for t1 to run.
...
..
.
t2: 97
t2: 98
t2: 99
t1: 1
t1: 2
t1: 3
...
..
.

If we change priorities of thread, we could see vice a versa of above table. Remember always high priority valued threads have more chance to run. Threads have a default value of 5. And there are some helper constants to help us while setting Thread property.

Thread.MIN_PRIORITY  (1)
Thread.NORM_PRIORITY  (5)
Thread.MAX_PRIORITY  (10)

Thread.yield()
yield() method stops execution of current running thread and give turn to another thread with same priority. This behaviour also is not guaranteed.

public class YieldRunnable implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(Thread.currentThread().getName() + ": " + i);
		}
	}
}
public class ThreadYield {
	public static void main(String[] args) {
		Thread t1 = new Thread(new YieldRunnable(),"t1");
		Thread t2 = new Thread(new YieldRunnable(),"t2");
		t1.setPriority(5);
		t2.setPriority(3);
		t1.start();
		t2.start();
	}
}

If we run above program, results could be like

t1: 396
t1: 397
t2: 0
t2: 1
t2: 2

As you see first t2 thread runs after t1 counter comes to 397. If we modify YieldRunner to use Thread.yield() method, what changes will happen at result.

public class YieldRunnable implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			Thread.yield();
			System.out.println(Thread.currentThread().getName() + ": " + i);
		}
	}
}

As you see scheduler switched between threads more frequently because Thread.yield() force scheduler to give up current running thread to select another one from thread pool.
t1: 0
t1: 1
t1: 2
t2: 0
t1: 3
t2: 1
t1: 4
t2: 2
t1: 5
t2: 3
t1: 6
t2: 4
t1: 7
t2: 5
t1: 8
t1: 9
t1: 10

join() Method

As its name, join() method starts a thread when another one is ended. If you have two threads and one of them is dependent to other one’s execution you should use join.

Thread t = new Thread();
t.start();
t.join();

In this code Thread t says “Hey current thread join me, and wait to run until I finish my job.”

Code Synchronization
Lets look at below code two cars (Porsche and Ferrari) are trying to pass a gate.

public class ThreadGate implements Runnable{
  boolean gateOpen = false;
  public static void main(String[] args){
    ThreadGate gateRunnable = new ThreadGate();
    Thread ferrari = new Thread(gateRunnable,"Ferrari");
    Thread porsche = new Thread(gateRunnable,"Porsche");
    ferrari.start();
    porsche.start();
  }
  public void run(){
    while(true){
      passTheGate();
    }
  }
  public void passTheGate(){
    decideGateState();
    if(gateOpen){
      System.out.println(Thread.currentThread().getName() + ": " + "Gate is open,I am going to pass gate in 2 seconds");
    }
    else{
      System.out.println(Thread.currentThread().getName() + ": " + "Gate is closed,I have to turn back :( ");
    }
    try{
      Thread.sleep(2000);
    }
    catch(Exception ex){
 
    }
    pass();
  }
  public void decideGateState(){
    gateOpen = Math.random() < 0.5 ? true : false;
  }
  public void pass(){
    if(gateOpen){
      System.out.println(Thread.currentThread().getName() + ": " + "I have just passed gate");
    }
    else{
      System.out.println(Thread.currentThread().getName() + ": " + "I have turned back.");
    }
  }
}

Output may be like this.

  1. Ferrari: Gate is closed,I have to turn back :(
  2. Porsche: Gate is open,I am going to pass gate in 2 seconds
  3. Ferrari: I have just passed gate
  4. Ferrari: Gate is closed,I have to turn back :(
  5. Porsche: I have turned back.

Have you noticed inconsistency at first three line. Ferrari said that, gate is closed and it will turn back, at first line but at third line Ferrari suddenly passed gate. So there are two options Ferrari can fly or we have code synchronization problem. While Ferrari waiting in front of gate it saw that gate is closed and it decided to turn back, mean while Porsche came and gate was opened for Porsche but Ferrari passed the gate which was opened for Porsche. At fifth line Porsche have to turn back because Ferrari took its turn.
I know Ferrari is fast but it should show respect to Porsche’s turn so we will synchronize our code.

public class ThreadGate implements Runnable{
  boolean gateOpen = false;
  public static void main(String[] args){
    ThreadGate gateRunnable = new ThreadGate();
    Thread ferrari = new Thread(gateRunnable,"Ferrari");
    Thread porsche = new Thread(gateRunnable,"Porsche");
    ferrari.start();
    porsche.start();
  }
  public void run(){
    while(true){
      passTheGate();
    }
  }
  public synchronized void passTheGate(){
    decideGateState();
    if(gateOpen){
      System.out.println(Thread.currentThread().getName() + ": " + "Gate is open,I am going to pass gate in 2 seconds");
    }
    else{
      System.out.println(Thread.currentThread().getName() + ": " + "Gate is closed,I have to turn back :( ");
    }
    try{
      Thread.sleep(500);
    }
    catch(Exception ex){
 
    }
    pass();
  }
  public void decideGateState(){
    gateOpen = Math.random() < 0.5 ? true : false;
  }
  public void pass(){
    if(gateOpen){
      System.out.println(Thread.currentThread().getName() + ": " + "I have just passed gate");
    }
    else{
      System.out.println(Thread.currentThread().getName() + ": " + "I have turned back.");
    }
  }
}

We have added synchronized keyword to passTheGate() method and lets run program again.

  1. Ferrari: Gate is closed,I have to turn back :(
  2. Ferrari: I have turned back.
  3. Ferrari: Gate is closed,I have to turn back :(
  4. Ferrari: I have turned back.
  5. Ferrari: Gate is open,I am going to pass gate in 2 seconds
  6. Ferrari: I have just passed gate
  7. Ferrari: Gate is open,I am going to pass gate in 2 seconds
  8. Ferrari: I have just passed gate
  9. Ferrari: Gate is closed,I have to turn back :(
  10. Ferrari: I have turned back.
  11. Ferrari: Gate is open,I am going to pass gate in 2 seconds
  12. Ferrari: I have just passed gate
  13. Ferrari: Gate is closed,I have to turn back :(
  14. Ferrari: I have turned back.
  15. Porsche: Gate is open,I am going to pass gate in 2 seconds
  16. Porsche: I have just passed gate
  17. Porsche: Gate is closed,I have to turn back :(
  18. Porsche: I have turned back.
  19. Porsche: Gate is open,I am going to pass gate in 2 seconds
  20. Porsche: I have just passed gate
  21. Porsche: Gate is closed,I have to turn back :(
  22. Porsche: I have turned back.
  23. Porsche: Gate is open,I am going to pass gate in 2 seconds
  24. Porsche: I have just passed gate
  25. Ferrari: Gate is open,I am going to pass gate in 2 seconds
  26. Ferrari: I have just passed gate
  27. Ferrari: Gate is closed,I have to turn back :(
  28. Ferrari: I have turned back.
  29. Porsche: Gate is closed,I have to turn back :(
  30. Porsche: I have turned back.
  31. Porsche: Gate is closed,I have to turn back :(

As you see, now they are waiting each other to pass gate or to turn back and they live happily together.

You should keep synchronized code as small as possible. If a method contains more than you want to synchronize then you should only synchronize desired part of that method.

In this code, two thread cannot enter synchronized block at the same time. One thread have to wait other one until it finishes its job.

public class PartialSync {
  public void someMethod() {
    System.out.println("Out of sync");
    synchronized (this) {
      System.out.println("Sync");
    }
  }
}

These two method also are same.

  public void someMethod() {
    synchronized (this) {
      System.out.println("Sync");
    }
  }

and

  public synchronized void someMethod() {
      System.out.println("Sync");
  }

Synchronizing Static Methods
Synchronization of static methods are not different from non-static methods.

  public static synchronized void someMethod() {
      System.out.println("Sync");
  }

and

  public static void someMethod() {
    synchronized (PartialSync.class){
      System.out.println("Sync");
    }
  }

Thread Safety
If you make required synchronization to protect class’ data so this class is thread safe. Many classes in Java API are already thread safe. StringBuffer and StringBuilder are nearly same except all methods in StringBuffer are synchronized. It is more appropriate to use StringBuffer in multi-threaded applications and StringBuilder in single-threaded applications.

Thread Deadlock
If one thread is locking resource A and waiting to lock resource B to release A and another thread is locking resource B and waiting to lock A to release B, but A is currently is locked by another thread. This scenario leads deadlock.

Thread Interaction

You can take a look at this hi-lo game to see thread interaction and how to use wait-notify methods.

public class QuestionThread extends Thread {
   Guess g = new Guess();
   public QuestionThread(String name) {
      super(name);
   }
   public static void main(String[] args) {
      //initialize threads
      QuestionThread questionThread = new QuestionThread("Question Thread");
      AnswerThread answerThread = new AnswerThread("Answer Thread", questionThread.g);
      //start threads
      questionThread.start();
      answerThread.start();
   }
   /*
    * Game loop.
    */
   public void run() {
      while (true) {
         //start new game
         g.startNewGame();
         do{
            //print higher or lower message.
           g.printInfoMessage();
         }while(!g.isWon());
         //if game is won, print message end jum to new game
         System.out.println("You won!!!");
      }
   }
}
public class Guess {
   int              randomNumber;
   int              currentGuess = randomNumber(); ;
   int              minGuess     = 0;
   int              maxGuess     = 100;
   static final int TRY_LOWER    = -1;
   static final int TRY_HIGHER   = 1;
   static final int WON          = 0;
   int              guessStat    = WON;
 
   public int getCurrentGuess() {
      return currentGuess;
   }
   /**
    * reset variables and start new game.
    */
   public void startNewGame(){
      minGuess = 0;
      maxGuess = 100;
      currentGuess = randomNumber();
      generateRandomNumber();
   }
   /**
    * select a new number to start new game
    */
   public synchronized void generateRandomNumber() {
      System.out.println("Try to guess random number");
      randomNumber = randomNumber();
      try {
         wait();
      }
      catch (InterruptedException e) {}
   }
 
   public synchronized void printInfoMessage() {
      if (guessStat == TRY_LOWER) {
         System.out.println("Try a lower number");
      }
      else if (guessStat == TRY_HIGHER) {
         System.out.println("Try a higher number");
      }
   }
 
   /**
    * @return - random nuber between 1-100
    */
   private int randomNumber() {
      return (int) (Math.random() * 100 + 1);
   }
 
   public synchronized void guess(int num) {
      System.out.println("num:"+num+",rand:"+randomNumber+",low:"+minGuess+",max:"+maxGuess);
      currentGuess = num;
      if (randomNumber < num) {
         guessStat = TRY_LOWER;
         maxGuess = num;
      }
      else if (randomNumber > num) {
         guessStat = TRY_HIGHER;
         minGuess = num;
      }
      else{
         guessStat = WON;
      }
      notify();
   }
 
   /**
    * @return- <code>true</code> if game is won else is <code>false</code>
    */
   public synchronized boolean isWon() {
      try {
         wait();
      }
      catch (InterruptedException e) {}
      return guessStat == WON;
   }
}
public class AnswerThread extends Thread {
   Guess g;
 
   public AnswerThread(String name, Guess g) {
      super(name);
      this.g = g;
   }
 
   public void run() {
      while (true) {
         try {
            Thread.sleep(2000);
         }
         catch (InterruptedException e) {}
         int num = 0;
         //try to approximate random number
         if (g.guessStat == Guess.TRY_HIGHER) {
            num = g.minGuess + ( g.maxGuess - g.minGuess ) / 2;
         }
         else {
            num = g.maxGuess - (g.maxGuess - g.minGuess)/2;
         }
         g.guess(num);
      }
   }
}

1 Comment »

  1. Loay said,

    July 10, 2011 at 4:11 am

    good tutorial.thanks…

RSS feed for comments on this post · TrackBack URL

Leave a Comment