Threads

Java's low-level API is based on the Thread, which can have a number of states .

  • NEW: A thread that has not been started.
  • RUNNABLE: A thread that is running in the JVM. It may not have the CPU.
  • BLOCKED: A thread that is waiting to enter a synchronized block (waiting for a monitor lock).
  • WAITING: A thread that waits indefinitely for another (wait, join operations).
  • TIMED_WAITING: A thread that waits a certain time for another (sleep, wait, join operations).
  • TERMINATED: A thread that has terminated. It cannot be executed again.

We can create a thread in two ways:

  • Extend the Thread class and rewrite the "run" method ( better not to use this method).
  • Implement the Runnable interface and its "run" method. Then create a Thread by passing this object to the constructor:
    • new Thread(new MyRunnable())

Once we have the Thread, we can run it using its start() method, which will change its state from NEW to RUNNABLE.

For the examples we will see below, we will use the following utility class:

public class Threads { private static long start = System.currentTimeMillis(); public static void log(String message) { System.out.println(String.format("%6d %-10s %s", System.currentTimeMillis() - start, Thread.currentThread().getName(), message)); } public static void spend(long millis) { long startTime = System.currentTimeMillis(); while (System.currentTimeMillis() - startTime < millis); } public static void rest(long millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { throw new RuntimeException(e); } } }

Its methods can be called after doing an import static Threads.*;.

Below we can see an example of creating a thread called "thread" from the main thread, "main". Shows the state of the "child" thread before and after its execution.

This would be the code:

public class StatesThread { static class MyRunnable implements Runnable { @Override public void run() { log("spending"); spend(750); log("resting"); rest(750); log("ending"); } } public static void main(String[] args) { Thread thread = new Thread(new MyRunnable(), "child"); log(thread.getState().name()); thread.start(); rest(250); log(thread.getState().name()); rest(875); log(thread.getState().name()); rest(500); log(thread.getState().name()); } }

This could be a possible console output:

0 main NEW 8 child spending 258 main RUNNABLE 758 child resting 1133 main TIMED_WAITING 1508 child ending 1633 main TERMINATED

This example presents no difficulties as no data is shared. No synchronization mechanism is used between the two threads either.