Java Threads

The procedure for creating threads based on the Runnable interface is as follows:

  1. A class implements the Runnable interface, providing the run() method that will be executed by the thread. An object of this class is a Runnable object.

  2. An object of Thread class is created by passing a Runnable object as argument to the Thread constructor. The Thread object now has a Runnable object that implements the run() method.

  3. The start() method is invoked on the Thread object created in the previous step. The start() method returns immediately after a thread has been spawned.

  4. The thread ends when the run() method ends, either by normal completion or by throwing an uncaught exception.

Note:Thread.currentThread() may return an output like Thread[threadA,5,main]
The output shown in bold describes the name of the thread, the priority of the thread, and the name of the group to which it belongs.

class RunnableThread implements Runnable {

    Thread runner;
    public RunnableThread() {
    }
    public RunnableThread(String threadName) {
        runner = new Thread(this, threadName); // (1) Create a new thread.
        System.out.println(runner.getName());
        runner.start(); // (2) Start the thread.
    }
    public void run() {
        //Display info about this particular thread
        System.out.println(Thread.currentThread());
    }
}

public class RunnableExample {

    public static void main(String[] args) {
        Thread thread1 = new Thread(new RunnableThread(), "thread1");
        Thread thread2 = new Thread(new RunnableThread(), "thread2");
        RunnableThread thread3 = new RunnableThread("thread3");
        //Start the threads
        thread1.start();
        thread2.start();
        try {
            //delay for one second
            Thread.currentThread().sleep(1000);
        } catch (InterruptedException e) {
        }
        //Display info about the main thread
        System.out.println(Thread.currentThread());
    }
}

Output:

thread3
Thread[thread3,5,main]
Thread[thread1,5,main]
Thread[thread2,5,main]
Thread[main,5,main]

Thread Synchronizations

Synchronized methods

public class SyncMethodsExample extends Thread {

    static String[] msg = { "Beginner", "java", "tutorial,", ".,", "com",
            "is", "the", "best" };
    public SyncMethodsExample(String id) {
        super(id);
    }
    public static void main(String[] args) {
        SyncMethodsExample thread1 = new SyncMethodsExample("thread1: ");
        SyncMethodsExample thread2 = new SyncMethodsExample("thread2: ");
        thread1.start();
        thread2.start();
        boolean t1IsAlive = true;
        boolean t2IsAlive = true;
        do {
            if (t1IsAlive && !thread1.isAlive()) {
                t1IsAlive = false;
                System.out.println("t1 is dead.");
            }
            if (t2IsAlive && !thread2.isAlive()) {
                t2IsAlive = false;
                System.out.println("t2 is dead.");
            }
        } while (t1IsAlive || t2IsAlive);
    }
    void randomWait() {
        try {
            Thread.currentThread().sleep((long) (3000 * Math.random()));
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        }
    }
    public synchronized void run() {
        SynchronizedOutput.displayList(getName(), msg);
    }
}

class SynchronizedOutput {

    // if the 'synchronized' keyword is removed, the message
    // is displayed in random fashion
    public static synchronized void displayList(String name, String list[]) {
        for (int i = 0; i < list.length; i++) {
            SyncMethodsExample t = (SyncMethodsExample) Thread
                    .currentThread();
            t.randomWait();
            System.out.println(name + list[i]);
        }
    }
}

Output:

thread1: Beginner
thread1: java
thread1: tutorial,
thread1: .,
thread1: com
thread1: is
thread1: the
thread1: best
t1 is dead.
thread2: Beginner
thread2: java
thread2: tutorial,
thread2: .,
thread2: com
thread2: is
thread2: the
thread2: best
t2 is dead.

Synchronized blocks

public class SyncBlockExample extends Thread {

    static String[] msg = { "Beginner", "java", "tutorial,", ".,", "com",
            "is", "the", "best" };
    public SyncBlockExample(String id) {
        super(id);
    }
    public static void main(String[] args) {
        SyncBlockExample thread1 = new SyncBlockExample("thread1: ");
        SyncBlockExample thread2 = new SyncBlockExample("thread2: ");
        thread1.start();
        thread2.start();
        boolean t1IsAlive = true;
        boolean t2IsAlive = true;
        do {
            if (t1IsAlive && !thread1.isAlive()) {
                t1IsAlive = false;
                System.out.println("t1 is dead.");
            }
            if (t2IsAlive && !thread2.isAlive()) {
                t2IsAlive = false;
                System.out.println("t2 is dead.");
            }
        } while (t1IsAlive || t2IsAlive);
    }
    void randomWait() {
        try {
            Thread.currentThread().sleep((long) (3000 * Math.random()));
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        }
    }
    public void run() {
        synchronized (System.out) {
            for (int i = 0; i < msg.length; i++) {
                randomWait();
                System.out.println(getName() + msg[i]);
            }
        }
    }
}

Output:

thread1: Beginner
thread1: java
thread1: tutorial,
thread1: .,
thread1: com
thread1: is
thread1: the
thread1: best
t1 is dead.
thread2: Beginner
thread2: java
thread2: tutorial,
thread2: .,
thread2: com
thread2: is
thread2: the
thread2: best
t2 is dead.

Thread States

  • NEW State
    A thread is in this state when the instantiation of a Thread object creates a new thread but does not start it running. A thread starts life in the Ready-to-run state. You can call only the start() or stop() methods when the thread is in this state. Calling any method besides start() or stop() causes an IllegalThreadStateException.

  • RUNNABLE
    When the start() method is invoked on a New Thread() it gets to the runnable state or running state by calling the run() method. A Runnable thread may actually be running, or may be awaiting its turn to run.

  • NOT RUNNABLE
    A thread becomes Not Runnable when one of the following four events occurs:

    • When sleep() method is invoked and it sleeps for a specified amount of time
    • When suspend() method is invoked
    • When the wait() method is invoked and the thread waits for notification of a free resource or waits for the completion of another thread or waits to acquire a lock of an object.
    • The thread is blocking on I/O and waits for its completion

    Below describes how a thread switches form a non runnable to a runnable state:

    • If a thread has been put to sleep, then the specified number of milliseconds must elapse (or it must be interrupted).
    • If a thread has been suspended, then its resume() method must be invoked.
    • If a thread is waiting on a condition variable, whatever object owns the variable must relinquish it by calling either notify() or notifyAll().
    • If a thread is blocked on I/O, then the I/O must complete.
  • TERMINATED
    A thread enters this state when the run() method has finished executing or when the stop() method is invoked. Once in this state, the thread cannot ever run again.

Reference

参考资料
Synchronization vs Lock
深入研究 Java Synchronize 和 Lock 的区别与用法
Java Thread(线程)案例详解sleep和wait的区别
Java 8 Concurrency Tutorial: Synchronization and Locks