Java - Concurrency / Multi-threading

java

Articles
Semaphore
Dead locks

This page now also exist in my other system.

java.util.concurrent;

// Java Concurrency / Multi-threading
Runnable
Thread
ExecutorService
Executors.newSingleThreadExecutor()
Executors.newFixedThreadPool(10)
Executors.newScheduleThreadPool(10)
Callable
Future
join
yield
wait
notify
notifyAll
synchronized
synchronized(objectName) { ... }

java.util.concurrent.ThreadPoolExecutor 
java.util.concurrent.ScheduledThreadPoolExecutor

ProcessBuilder: A Java application can create additional processes using a ProcessBuilder object.

Using Future, we can obtain the result of the thread via the Runnable interface, 
or the return value of a Calleable's call method.

Static method can be synchronized.
Static methods and block are synchronized on the class.  Instance methods and blocks are synchronized
on the instance of the class.  Static synchronized methods and instance

We use threads when if we can execute independent tasks in parallel, and later re-join them if needed.

Each thread is associated with an instance of the class Thread.

An Runnable class implement the Runnable interface, which means it defines a method named run.

There are two ways to create threads:
1. By defining a class that implements the Runnable interface
2. By sub-classing the Thread class

// Create a thread using Runnable interface
public class HelloRunnable implements Runnable {
    public void run() {
        ...
    }
}

// We then have to create an instance of class that implements the Runnable, and
// create a new Thread object with the new runnable object, and then finally call
// the start method of the thread object
public static void main(String[] args) {
    Runnable runnable = new HelloRunnable();
    Thread thread = new Thread(runnable);
    thread.start();
}

// Create a thread by sub-classing the Thread class
public class HelloThread extends Thread {
    public void run() {
        ...
    }
}

public static void main(String[] args) {
    HelloThread thread = new HelloThread();
    thread.start();
}

// The Thread class implements the Runnable interface, but its run method does not do anything.
// In both cases, we start a thread using the start() method.

// Creating thread by implementing the Runnable interface is the preferred approach
// because a Runnable class can inherit from another class other than the Thread class.

// ExecutorService is a cool new way to execute a task in the background.  You can think 
// of the ExecutorService as similar to a thread pool.
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
  public void run() {
    ...
  }
});
executorService.shutdown();

// There are different ways to create Executor Services:
// 1. Using Executors.newSingleThreadExecutor();
// 2. Using Executor.newFixedThreadPool(10);
// 3. Using Executor.newScheduleThreadPool(10);

// The Executors.newSingleThreadExecutor() approach creates an Executor that use a single 
// worker thread operating off an unbounded queue.

// The Executor.newFixedThreadPool(10) approaches creates a thread pool that reuses a 
// fixed number of threads operating off a shared unbounded queue.  At any point, the 
// parameter specifies the most threads that will be active processing tasks.

// The Executor.newScheduleThreadPool(10) approach creates a thread pool that can schedule
// commands to run after a given delay or to execute periodically.

// We can use a Future to check the return value of a job that was run by an Executor Service:
ExecutorService executorService1 = Executors.newSingleThreadExecutor();
Future future = executorService1.submit(new Runnable() {
  public void run() {
    ..
  }
});
future.get(); // returns null if the task has finished correctly.

// The run method of the Runnable interface has a return type of void.  It cannot return 
// any result from executing a task.  However, the call method of the Callable interface
// has a return type.  If you have multiple return values from a task, we can use the 
// Callable interface.

Future futureFromCallable = executorService1.submit(new Callable() {
  public String call() throws Exception {
    return "RESULT";
  }
});
futureFromCallable.get();

// An interrupt is an indication to a thread that it should stop what it is doing and do something else.
// A thread can interrupt another thread by invoking the interrupt method of the Thread class.

// There are two approach for handing interrupts:
// 1. Using try / catch to catch the InterruptedException
// 2. Using Thread.interrupted method

public class SimpleThreads {

    // Display a message, preceded by the name of the current thread
    static void threadMessage(String message) {
        String threadName = Thread.currentThread().getName();
        System.out.format("%s: %s%n",
                          threadName,
                          message);
    }

    private static class MessageLoop implements Runnable {
        public void run() {
            String importantInfo[] = {
                "Mares eat oats",
                "Does eat oats",
                "Little lambs eat ivy",
                "A kid will eat ivy too"
            };
            try {
                for (int i = 0; i < importantInfo.length; i++) {
                    // Pause for 4 seconds
                    Thread.sleep(4000);
                    // Print a message
                    threadMessage(importantInfo[i]);
                }
            } catch (InterruptedException e) {
                threadMessage("I wasn't done!");
            }
        }
    }

    public static void main(String args[])
        throws InterruptedException {

        // Delay, in milliseconds before we interrupt MessageLoop
        // thread (default one hour).
        long patience = 1000 * 60 * 60;

        // If command line argument
        // present, gives patience
        // in seconds.
        if (args.length > 0) {
            try {
                patience = Long.parseLong(args[0]) * 1000;
            } catch (NumberFormatException e) {
                System.err.println("Argument must be an integer.");
                System.exit(1);
            }
        }

        threadMessage("Starting MessageLoop thread");
        long startTime = System.currentTimeMillis();
        Thread t = new Thread(new MessageLoop());
        t.start();

        threadMessage("Waiting for MessageLoop thread to finish");
        // loop until MessageLoop
        // thread exits
        while (t.isAlive()) {
            threadMessage("Still waiting...");
            // Wait maximum of 1 second
            // for MessageLoop thread
            // to finish.
            t.join(1000);
            if (((System.currentTimeMillis() - startTime) > patience)
                  && t.isAlive()) {
                threadMessage("Tired of waiting!");
                t.interrupt();
                // Shouldn't be long now
                // -- wait indefinitely
                t.join();
            }
        }
        threadMessage("Finally!");
    }
}

// There are two basic approaches for synchronization:
// 1. synchronized methods
// 2. synchronize statements

// We can make a method synchronized by simplying adding the synchronized keyword
// to its declaration.

// Making synchronized method has two effects:
// 1.  It is not possible for two invocation of synchronized methods on the same
//     object to interleave.  When one thread is executing a synchronized method
//     for an object, all other threads that invoke synchronized methods for the
//     same object block (suspend execution) until the first thread is done with
//     with the object.
// 2.  When a synchronized method exits, it automatically establishes a 
//     happens-before relationship with any subsequent invocation of a synchronized
//     method for the same object.  This guarantees that changes to the state of
//     the object are visible to all threads.

// We cannot use the synchronized keyword on a constructor.  Synchronizing 
// constructors does not make any sense, because only the thread that creates
// an object should have access to it while it is being constructed.

// Instrinsic lock:
// Synchronization is built around an internal entity known as the intrinsic lock
// or monitor lock.  The API specification often refers to this entity as a monitor.
// Instrinsic locks play a role in both aspects of synchrnonization, enforcing
// exclusive access to an object's state and establishing happens-before relationship
// that are essential to visibility.  Every object has an intrinsic lock associated
// with it.  By convention, a thread that needs exclusive and consistent access to
// an object's fields has to acquire the object's instrinsic lock before accessing 
// them, and then release the instrinsic lock when it's done with them.  A thread is
// said to own the instrinsic lock between the time it has acquired the lock and 
// released the lock.  As long as a thread owns an instrinsic lock, no other thread
// can acquire the same lock.  The other thread will block when it attempts to 
// acquire the lock.  When a thread releases an instrinsic lock, a happens-before
// relationship is established between that action and any subsequent
// acquisition of the same lock.

// When a thread invokes a synchronized method, it automatically acquires the 
// instrinsic lock for that method's object and release it when the method returns.
// The lock release occurs even if the return was caused by an uncaught exception.

// The synchronized keyword can be applied to a static method.  When a static 
// synchronized method is invoked, because the static method is associated with
// the class, not an object, the thread acquires the instrinsic lock for the Class
// object associated with the class.  Therefore, access to the class's static field
// is controlled by a lock that is distinct from the lock for any instance of the 
// class.

// Unlike synchronized methods, synchronized statements (or blocks) must specify
// the object that provides the instrinsic lock:
public void addName(String name) {
    synchronized(this) {
        lastName = name;
        nameCount++;
    }
    nameList.add(name);
}

// The above code specifies the this object as parameter to the synchronized statement.

// In the above example, the addName method needs to synchronize changes to lastName
// and nameCount, but also need to avoid synchronizing invocations of other objects'
// methods.  Invoking synchronized methods from other other objects can create problems.
// Without synchronized statements, there would have to be a separate unsynchronized
// method for the sole purpose of invoking nameList.add.

// Synchronized statements are useful for improving concurrency.  Suppose, for example, 
// class MsLunch has two instance fields, c1 and c2, that are never used together. All 
// updates of these fields must be synchronized, but there's no reason to prevent an 
// update of c1 from being interleaved with an update of c2 — and doing so reduces 
// concurrency by creating unnecessary blocking. Instead of using synchronized methods 
// or otherwise using the lock associated with this, we create two objects solely to 
// provide locks.

public class MsLunch {
    private long c1 = 0;
    private long c2 = 0;
    private Object lock1 = new Object();
    private Object lock2 = new Object();

    public void inc1() {
        synchronized(lock1) {
            c1++;
        }
    }

    public void inc2() {
        synchronized(lock2) {
            c2++;
        }
    }
}

// Use this idiom with extreme care. You must be absolutely sure that it really is safe 
// to interleave access of the affected fields.

// Reentrant synchronization:
// A thread cannot acquire a lock owned by another thread. But a thread can acquire a 
// lock that it already owns. Allowing a thread to acquire the same lock more than once 
// enables reentrant synchronization. This describes a situation where synchronized code, 
// directly or indirectly, invokes a method that also contains synchronized code, and 
// both sets of code use the same lock. Without reentrant synchronization, synchronized 
// code would have to take many additional precautions to avoid having a thread cause 
// itself to block.

// Different states of a thread object
// NEW: The thread object is created by the start method has not yet been invoked.
// RUNNABLE: A number of threads can be in the RUNNABLE state.  The scheduler 
//           determine which thread to run.
// RUNNING: This thread is running.
// BLOCKED / WAITING: The thread is waiting for something such as IO operation to complete.
// TERMINATED / DEAD: The thread has complete its execution.

// The scheduler can be requested to allot more CPU to a thread by increasing the threads 
// priority.  Each thread in Java is assigned a default priority 5.  This priority can be 
// increased or decreased between the range of 1 and 10.

// To set priority for a thread:
t.setPriority(8);
t.setPriority(Thread.MAX_PRIORITY);
t.setPriority(Thread.MIN_PRIORITY);
t.setPriority(Thread.NORMAL_PRIORITY);

// To start one thread only after another thread has finish, use the join method:
thread3.start();
thread2.start();
thread3.join(); // wait for thread3 to complete
thread4.start();

// The join method can accept a time in milliseconds as a parameter:
thread4.join(2000);

// In the above example, the main thread would wait for 2000 milliseconds 
// or the end of execution of thread4 whichever is minimum.

// To yield to another thread, use the yield method.  It is a static method from
// the Thread class, so we Thread.yield().

// A thread can also sleep for some time using the sleep method.

// The wait method cause the thread to wait until it is notified.
synchronized(thread) {
  thread.start();
  thread.wait();
}

// In the above code, we create a thread, and we tell it to wait.

// To notify a thread, use the notify method:
synchronize (this) {
  calculateSumUpToMillion();
  notify();
}

// If more than one thread is waiting for an object, we can notify all the 
// threads by using the notifyAll method.

// Example of using wait and notify:
class Calculator extends Thread {
  long sum;
  public void run() {
    synchronized (this) {
      for (int i = 0; i < 10000000; i++) {
        sum += i;
      }
      notify();
    }
  }
}

public class ThreadWaitAndNotify {
  public static void main(String[] args) {
    Calculator thread = new Calculator();
    thread.start();
    synchronized (thread) {
      try {
        thread.wait();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    System.out.println(thread.sum);
  }
}

// The volatile keyword is used to indicate that a variable will be modified 
// by different threads.  Declaring a volatile Java variable means:
// 1. The value of this variable will never be cached thread-locally: all 
//    reads and writes will go straight to "main memory".
// 2. Access to the variable acts as though it is enclosed in a synchronized 
//    block, synchronized on itself.  We say "acts as though", because to the 
/     programmer at least (and probably in most JVM implementations) there is 
//    no actual lock object involved. Here is how synchronized and volatile compare:

// The main differences between synchronized and volatile are:
// 1.  a primitive variable may be declared volatile (whereas you can't synchronize 
//     on a primitive with synchronized).
// 2.  an access to a volatile variable never has the potential to block: we're only 
//     ever doing a simple read or write, so unlike a synchronized block we will never 
//     hold on to any lock.   
// 3.  because accessing a volatile variable never holds a lock, it is not suitable 
//     for cases where we want to read-update-write as an atomic operation (unless 
//     we're prepared to "miss an update")
// 4.  a volatile variable that is an object reference may be null (because you're 
//     effectively synchronizing on the reference, not the actual object). 
// 5.  Attempting to synchronize on a null object will throw a NullPointerException. 

Threads exist within a process — every process has at least one. Threads share 
the process's resources, including memory and open files.

Two overloaded versions of sleep are provided: one that specifies the sleep time 
to the millisecond and one that specifies the sleep time to the nanosecond. 
However, these sleep times are not guaranteed to be precise, because they are 
limited by the facilities provided by the underlying OS. The sleep period can 
also be terminated by interrupts.  In any case, you cannot assume that invoking 
sleep will suspend the thread for precisely the time period specified.

An interrupt is an indication to a thread that it should stop what it is doing 
and do something else. It's up to the programmer to decide exactly how a thread 
responds to an interrupt, but it is very common for the thread to terminate.

How does a thread support its own interruption? This depends on what it's 
currently doing. If the thread is frequently invoking methods that throw 
InterruptedException, it simply returns from the run method after it catches 
that exception.

for (int i = 0; i < importantInfo.length; i++) {
    // Pause for 4 seconds
    try {
        Thread.sleep(4000);
    } catch (InterruptedException e) {
        // We've been interrupted: no more messages.
        // return;
    }
    // Print a message
    System.out.println(importantInfo[i]);
}

In the above code, when the thread is interrupted, it immediately wake up and
print the message, and continue with the for loop, which then go back to sleep
again.

If a thread does not invoke a method that throws the InterruptedException, it
should periodically invoke Thread.interrupted() to check to see if it was 
interrupted.

The interrupt mechanism is implemented using an internal flag known as the 
interrupt status. Invoking Thread.interrupt sets this flag. When a thread checks 
for an interrupt by invoking the static method Thread.interrupted, interrupt 
status is cleared. The non-static isInterrupted method, which is used by one 
thread to query the interrupt status of another, does not change the interrupt 
status flag.

By convention, any method that exits by throwing an InterruptedException clears 
interrupt status when it does so. However, it's always possible that interrupt 
status will immediately be set again, by another thread invoking interrupt.

Overloads of join allow the programmer to specify a waiting period. However, 
as with sleep, join is dependent on the OS for timing, so you should not assume 
that join will wait exactly as long as you specify.

Like sleep, join responds to an interrupt by exiting with an InterruptedException.

while (t.isAlive()) { ... }

t.join(1000);

// The above code waits a maximum of 1 second.  If the thread does not finish
// within 1 second, and it if it is still alive, we are going to interrupt it:

if (((System.currentTimeMillis() - startTime > patience) && t.isAlive()) {
  t.interrupt();
  t.join();
}

If threadA want to interrupt threadB, use threadB.interrupt()

Two kinds of errors possible: thread interference and memory consistency errors.

Synchronization can introduce thread contention, which occurs when two or more 
threads try to access the same resource simultaneously and cause the Java 
runtime to execute one or more threads more slowly, or even suspend their 
execution. Starvation and livelock are forms of thread contention.

Interference happens when two operations, running in different threads, but 
acting on the same data, interleave. 

There are several actions that create happens-before relationships:
Synchronization
When a statement invokes Thread.start, every statement that has a happens-before 
relationship with that statement also has a happens-before relationship with 
every statement executed by the new thread. The effects of the code that led up 
to the creation of the new thread are visible to the new thread.

When a thread terminates and causes a Thread.join in another thread to return, 
then all the statements executed by the terminated thread have a happens-before 
relationship with all the statements following the successful join. The effects 
of the code in the thread are now visible to the thread that performed the join.

Note that constructors cannot be synchronized — using the synchronized keyword 
with a constructor is a syntax error. Synchronizing constructors doesn't make 
sense, because only the thread that creates an object should have access to it 
while it is being constructed.

When constructing an object that will be shared between threads, be very careful 
that a reference to the object does not "leak" prematurely. For example, 
suppose you want to maintain a List called instances containing every instance 
of class. You might be tempted to add the following line to your constructor:
instances.add(this);
But then other threads can use instances to access the object before 
construction of the object is complete.  

Atomic action is one that effectively happens all at once. An atomic action 
cannot stop in the middle: it either happens completely, or it doesn't happen 
at all. No side effects of an atomic action are visible until the action is 
complete.

Reads and writes are atomic for reference variables and for most primitive 
variables (all types except long and double).

Reads and writes are atomic for all variables declared volatile (including long 
and double variables).

Atomic actions cannot be interleaved, so they can be used without fear of thread 
interference. However, this does not eliminate all need to synchronize atomic 
actions, because memory consistency errors are still possible. Using volatile 
variables reduces the risk of memory consistency errors, because any write to a 
volatile variable establishes a happens-before relationship with subsequent 
reads of that same variable. This means that changes to a volatile variable are 
always visible to other threads. What's more, it also means that when a thread 
reads a volatile variable, it sees not just the latest change to the volatile, 
but also the side effects of the code that led up the change.

Using simple atomic variable access is more efficient than accessing these 
variables through synchronized code, but requires more care by the programmer 
to avoid memory consistency errors. Whether the extra effort is worthwhile 
depends on the size and complexity of the application.

A concurrent application's ability to execute in a timely manner is known as 
its liveness.

Deadlock happens when threadA is waiting for threadB, but threadB is also waiting
for threadA.

Starvation describes a situation where a thread is unable to gain regular access 
to shared resources and is unable to make progress. This happens when shared 
resources are made unavailable for long periods by "greedy" threads. For example, 
suppose an object provides a synchronized method that often takes a long time 
to return. If one thread invokes this method frequently, other threads that also 
need frequent synchronized access to the same object will often be blocked.

Livelock: A thread often acts in response to the action of another thread. If 
the other thread's action is also a response to the action of another thread, 
then livelock may result. As with deadlock, livelocked threads are unable to 
make further progress. However, the threads are not blocked — they are simply 
too busy responding to each other to resume work.

Guarded Blocks:  Threads often have to coordinate their actions. The most 
common coordination idiom is the guarded block. Such a block begins by polling 
a condition that must be true before the block can proceed.

A more efficient guard invokes Object.wait to suspend the current thread. The 
invocation of wait does not return until another thread has issued a 
notification that some special event may have occurred — though not necessarily 
the event this thread is waiting for:

public synchronized void guardedJoy() {
    // This guard only loops once for each special event, which may not
    // be the event we're waiting for.
    while(!joy) {
        try {
            wait();
        } catch (InterruptedException e) {}
    }
    System.out.println("Joy and efficiency have been achieved!");
}

Always invoke wait inside a loop that tests for the condition being waited for. 
Don't assume that the interrupt was for the particular condition you were 
waiting for, or that the condition is still true. 

Suppose d is the object we're using to invoke wait. When a thread invokes 
d.wait, it must own the intrinsic lock for d — otherwise an error is thrown. 
Invoking wait inside a synchronized method is a simple way to acquire the 
intrinsic lock.  When wait is invoked, the thread releases the lock and suspends 
execution. At some future time, another thread will acquire the same lock and 
invoke Object.notifyAll, informing all threads waiting on that lock that 
something important has happened:

public synchronized notifyJoy() {
    joy = true;
    notifyAll();
}

Some time after the second thread has released the lock, the first thread 
reacquires the lock and resumes its operation.

here is a second notification method, notify, which wakes up a single thread. 
Because notify doesn't allow you to specify the thread that is woken up, it is 
useful only in massively parallel applications — that is, programs with a large 
number of threads, all doing similar chores. In such an application, you don't 
care which thread gets woken up. 

The biggest advantage of Lock objects over implicit locks is their ability to 
back out of an attempt to acquire a lock. The tryLock method backs out if the 
lock is not available immediately or before a timeout expires (if specified). 
The lockInterruptibly method backs out if another thread sends an interrupt 
before the lock is acquired.

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.Random;

public class Safelock {
    static class Friend {
        private final String name;
        private final Lock lock = new ReentrantLock();

        public Friend(String name) {
            this.name = name;
        }

        public String getName() {
            return this.name;
        }

        public boolean impendingBow(Friend bower) {
            Boolean myLock = false;
            Boolean yourLock = false;
            try {
                myLock = lock.tryLock();
                yourLock = bower.lock.tryLock();
            } finally {
                if (! (myLock && yourLock)) {
                    if (myLock) {
                        lock.unlock();
                    }
                    if (yourLock) {
                        bower.lock.unlock();
                    }
                }
            }
            return myLock && yourLock;
        }

        public void bow(Friend bower) {
            if (impendingBow(bower)) {
                try {
                    System.out.format("%s: %s has"
                        + " bowed to me!%n", 
                        this.name, bower.getName());
                    bower.bowBack(this);
                } finally {
                    lock.unlock();
                    bower.lock.unlock();
                }
            } else {
                System.out.format("%s: %s started"
                    + " to bow to me, but saw that"
                    + " I was already bowing to"
                    + " him.%n",
                    this.name, bower.getName());
            }
        }

        public void bowBack(Friend bower) {
            System.out.format("%s: %s has" +
                " bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    static class BowLoop implements Runnable {
        private Friend bower;
        private Friend bowee;

        public BowLoop(Friend bower, Friend bowee) {
            this.bower = bower;
            this.bowee = bowee;
        }

        public void run() {
            Random random = new Random();
            for (;;) {
                try {
                    Thread.sleep(random.nextInt(10));
                } catch (InterruptedException e) {}
                bowee.bow(bower);
            }
        }
    }

    public static void main(String[] args) {
        final Friend alphonse =
            new Friend("Alphonse");
        final Friend gaston =
            new Friend("Gaston");
        new Thread(new BowLoop(alphonse, gaston)).start();
        new Thread(new BowLoop(gaston, alphonse)).start();
    }
}

Executor, a simple interface that supports launching new tasks.
ExecutorService, a subinterface of Executor, which adds features that help 
  manage the lifecycle, both of the individual tasks and of the executor itself.
ScheduledExecutorService, a subinterface of ExecutorService, supports future 
  and/or periodic execution of tasks.

The Executor interface provides a single method, execute, designed to be a 
drop-in replacement for a common thread-creation idiom. If r is a Runnable 
object, and e is an Executor object you can: e.execute(r);

However, the definition of execute is less specific. The low-level idiom 
creates a new thread and launches it immediately. Depending on the Executor 
implementation, execute may do the same thing, but is more likely to use an 
existing worker thread to run r, or to place r in a queue to wait for a 
worker thread to become available.

The ExecutorService interface supplements execute with a similar, but more 
versatile submit method. Like execute, submit accepts Runnable objects, but 
also accepts Callable objects, which allow the task to return a value. The 
submit method returns a Future object, which is used to retrieve the Callable 
return value and to manage the status of both Callable and Runnable tasks.

ExecutorService also provides methods for submitting large collections of 
Callable objects. Finally, ExecutorService provides a number of methods for 
managing the shutdown of the executor. To support immediate shutdown, tasks 
should handle interrupts correctly.

The ScheduledExecutorService interface supplements the methods of its parent 
ExecutorService with schedule, which executes a Runnable or Callable task after 
a specified delay. In addition, the interface defines scheduleAtFixedRate and 
scheduleWithFixedDelay, which executes specified tasks repeatedly, at defined 
intervals.

One common type of thread pool is the fixed thread pool. This type of pool 
always has a specified number of threads running; if a thread is somehow 
terminated while it is still in use, it is automatically replaced with a 
new thread. Tasks are submitted to the pool via an internal queue, which 
holds extra tasks whenever there are more active tasks than threads.

The newCachedThreadPool method creates an executor with an expandable thread 
pool. This executor is suitable for applications that launch many short-lived 
tasks.

The fork/join framework is an implementation of the ExecutorService interface 
that helps you take advantage of multiple processors. It is designed for work 
that can be broken into smaller pieces recursively. The goal is to use all the 
available processing power to enhance the performance of your application.

As with any ExecutorService implementation, the fork/join framework distributes 
tasks to worker threads in a thread pool. The fork/join framework is distinct 
because it uses a work-stealing algorithm. Worker threads that run out of 
things to do can steal tasks from other threads that are still busy.

The center of the fork/join framework is the ForkJoinPool class, an extension 
of the AbstractExecutorService class. ForkJoinPool implements the core work-
stealing algorithm and can execute ForkJoinTask processes.

The first step for using the fork/join framework is to write code that performs 
a segment of the work. Your code should look similar to the following pseudocode:

if (my portion of the work is small enough)
  do the work directly
else
  split my work into two pieces
  invoke the two pieces and wait for the results

Wrap this code in a ForkJoinTask subclass, typically using one of its more 
specialized types, either RecursiveTask (which can return a result) or 
RecursiveAction.

After your ForkJoinTask subclass is ready, create the object that represents all 
the work to be done and pass it to the invoke() method of a ForkJoinPool instance.

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import javax.imageio.ImageIO;

/**
 * ForkBlur implements a simple horizontal image blur. It averages pixels in the
 * source array and writes them to a destination array. The sThreshold value
 * determines whether the blurring will be performed directly or split into two
 * tasks.
 *
 * This is not the recommended way to blur images; it is only intended to
 * illustrate the use of the Fork/Join framework.
 */
public class ForkBlur extends RecursiveAction {

    private int[] mSource;
    private int mStart;
    private int mLength;
    private int[] mDestination;
    private int mBlurWidth = 15; // Processing window size, should be odd.

    public ForkBlur(int[] src, int start, int length, int[] dst) {
        mSource = src;
        mStart = start;
        mLength = length;
        mDestination = dst;
    }

    // Average pixels from source, write results into destination.
    protected void computeDirectly() {
        int sidePixels = (mBlurWidth - 1) / 2;
        for (int index = mStart; index < mStart + mLength; index++) {
            // Calculate average.
            float rt = 0, gt = 0, bt = 0;
            for (int mi = -sidePixels; mi <= sidePixels; mi++) {
                int mindex = Math.min(Math.max(mi + index, 0), mSource.length - 1);
                int pixel = mSource[mindex];
                rt += (float) ((pixel & 0x00ff0000) >> 16) / mBlurWidth;
                gt += (float) ((pixel & 0x0000ff00) >> 8) / mBlurWidth;
                bt += (float) ((pixel & 0x000000ff) >> 0) / mBlurWidth;
            }

            // Re-assemble destination pixel.
            int dpixel = (0xff000000)
                    | (((int) rt) << 16)
                    | (((int) gt) << 8)
                    | (((int) bt) << 0);
            mDestination[index] = dpixel;
        }
    }
    protected static int sThreshold = 10000;

    @Override
    protected void compute() {
        if (mLength < sThreshold) {
            computeDirectly();
            return;
        }

        int split = mLength / 2;

        invokeAll(new ForkBlur(mSource, mStart, split, mDestination),
                new ForkBlur(mSource, mStart + split, mLength - split, 
                mDestination));
    }

    // Plumbing follows.
    public static void main(String[] args) throws Exception {
        String srcName = "red-tulips.jpg";
        File srcFile = new File(srcName);
        BufferedImage image = ImageIO.read(srcFile);

        System.out.println("Source image: " + srcName);

        BufferedImage blurredImage = blur(image);

        String dstName = "blurred-tulips.jpg";
        File dstFile = new File(dstName);
        ImageIO.write(blurredImage, "jpg", dstFile);

        System.out.println("Output image: " + dstName);

    }

    public static BufferedImage blur(BufferedImage srcImage) {
        int w = srcImage.getWidth();
        int h = srcImage.getHeight();

        int[] src = srcImage.getRGB(0, 0, w, h, null, 0, w);
        int[] dst = new int[src.length];

        System.out.println("Array size is " + src.length);
        System.out.println("Threshold is " + sThreshold);

        int processors = Runtime.getRuntime().availableProcessors();
        System.out.println(Integer.toString(processors) + " processor"
                + (processors != 1 ? "s are " : " is ")
                + "available");

        ForkBlur fb = new ForkBlur(src, 0, src.length, dst);

        ForkJoinPool pool = new ForkJoinPool();

        long startTime = System.currentTimeMillis();
        pool.invoke(fb);
        long endTime = System.currentTimeMillis();

        System.out.println("Image blur took " + (endTime - startTime) + 
                " milliseconds.");

        BufferedImage dstImage =
                new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        dstImage.setRGB(0, 0, w, h, dst, 0, w);

        return dstImage;
    }
}

The java.util.concurrent.atomic package defines classes that support atomic 
operations on single variables. All classes have get and set methods that work 
like reads and writes on volatile variables. That is, a set has a happens-before 
relationship with any subsequent get on the same variable. The atomic 
compareAndSet method also has these memory consistency features, as do the 
simple atomic arithmetic methods that apply to integer atomic variables.

java.util.concurrent.atomic.AtomicInteger
ThreadLocalRandom

For concurrent access, using ThreadLocalRandom instead of Math.random() results 
in less contention and, ultimately, better performance.  All you need to do is 
call ThreadLocalRandom.current(), then call one of its methods to retrieve a 
random number. Here is one example:  
int r = ThreadLocalRandom.current() .nextInt(4, 77);

When should we use threads?

We use threads when if we can execute independent tasks in parallel, and later re-join them if needed.

What class does each thread associated with?

Each thread is associated with an instance of the class Thread.

What is a Runnable object?

An Runnable class implement the Runnable interface, which means it defines a method named run.

What are the two different way to implement a thread?

  • By defining a Runnable object
  • By sub-classing the Thread class

How can I define a thread using a Runnable class?

public class HelloRunnable implements Runnable {
    public void run() {
        ...
    }

    public static void main(String[] args) {
        (new Thread(new HelloRunnable())).start();
    }
}

The Runnable object is passed to the Thread constructor.

How can I implement a thread by sub-classing the Thread class?

public class HelloThread extends Thread {
    public void run() {
    }
    public static void main(String[] args) {
        (new HelloThread()).start();
    }
}

The Thread class itself implements the Runnable interface, but its run method does not do anything.

In both cases, we start a thread using the start() method.

When should we implement multi-threading by sub-classing the Thread class, and when should we do it using a Runnable?

The "Using Runnable" approach is generally the preferred approach because a Runnable class can inherit from another class other than the Thread class.

What is an interrupt?

An interrupt is an indication to a thread that it should stop what it is doing and do something else.

How can a thread interrupt another thread?

A thread sends an interrupt by invoking interrupt on the Thread object.

What are the two approaches for handling interrupts?

  • Using try / catch to catch the InterruptedException
  • Using Thread.interrupted()

What are thetwo basic strategies for using Thread objects to create a concurrent application?

There are two basic strategies for using Thread objects to create a concurrent application:

  1. Directly control thread creation and management, simply instantiate Thread each time the application needs to initiate an asynchronous task.
  2. Abstract thread management from the rest of your application, pass the application's tasks to an executor.

A thread example:

public class SimpleThreads {

    // Display a message, preceded by the name of the current thread
    static void threadMessage(String message) {
        String threadName = Thread.currentThread().getName();
        System.out.format("%s: %s%n",
                          threadName,
                          message);
    }

    private static class MessageLoop
        implements Runnable {
        public void run() {
            String importantInfo[] = {
                "Mares eat oats",
                "Does eat oats",
                "Little lambs eat ivy",
                "A kid will eat ivy too"
            };
            try {
                for (int i = 0;
                     i < importantInfo.length;
                     i++) {
                    // Pause for 4 seconds
                    Thread.sleep(4000);
                    // Print a message
                    threadMessage(importantInfo[i]);
                }
            } catch (InterruptedException e) {
                threadMessage("I wasn't done!");
            }
        }
    }

    public static void main(String args[])
        throws InterruptedException {

        // Delay, in milliseconds before
        // we interrupt MessageLoop
        // thread (default one hour).
        long patience = 1000 * 60 * 60;

        // If command line argument
        // present, gives patience
        // in seconds.
        if (args.length > 0) {
            try {
                patience = Long.parseLong(args[0]) * 1000;
            } catch (NumberFormatException e) {
                System.err.println("Argument must be an integer.");
                System.exit(1);
            }
        }

        threadMessage("Starting MessageLoop thread");
        long startTime = System.currentTimeMillis();
        Thread t = new Thread(new MessageLoop());
        t.start();

        threadMessage("Waiting for MessageLoop thread to finish");
        // loop until MessageLoop
        // thread exits
        while (t.isAlive()) {
            threadMessage("Still waiting...");
            // Wait maximum of 1 second
            // for MessageLoop thread
            // to finish.
            t.join(1000);
            if (((System.currentTimeMillis() - startTime) > patience)
                  && t.isAlive()) {
                threadMessage("Tired of waiting!");
                t.interrupt();
                // Shouldn't be long now
                // -- wait indefinitely
                t.join();
            }
        }
        threadMessage("Finally!");
    }
}

What are the two basic approaches for synchronization?

  • synchronized methods
  • synchronized statements

How can we make a method synchronized?

To make a method synchronized, simply add the synchronized keyword to its declaration.

What are the effects of making a synchronized method?

public class SynchronizedCounter {
    private int c = 0;

    public synchronized void increment() {
        c++;
    }

    public synchronized void decrement() {
        c--;
    }

    public synchronized int value() {
        return c;
    }
}

If count is an instance of SynchronizedCounter, then making these methods synchronized has two effects:

  1. First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
  2. Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.

Can we use the synchronized keyword on a constructor?

No. Constructors cannot be synchronized — using the synchronized keyword with a constructor is a syntax error. Synchronizing constructors doesn't make sense, because only the thread that creates an object should have access to it while it is being constructed..

What is an instrinsic lock?

Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.

Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.

When a thread releases an intrinsic lock, a happens-before relationship is established between that action and any subsequent acquisition of the same lock.

What happens to the instrinsic lock when a thread invoke a synchronized method?

When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.

What happens to the instrinsic lock when a static synchronized method is invoked?

You might wonder what happens when a static synchronized method is invoked, since a static method is associated with a class, not an object. In this case, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.

How can we use synchronized statements?

Another way to create synchronized code is with synchronized statements. Unlike synchronized methods, synchronized statements must specify the object that provides the intrinsic lock:

public void addName(String name) {
    synchronized(this) {
        lastName = name;
        nameCount++;
    }
    nameList.add(name);
}

In this example, the addName method needs to synchronize changes to lastName and nameCount, but also needs to avoid synchronizing invocations of other objects' methods. (Invoking other objects' methods from synchronized code can create problems that are described in the section on Liveness.) Without synchronized statements, there would have to be a separate, unsynchronized method for the sole purpose of invoking nameList.add.

Synchronized statements are also useful for improving concurrency with fine-grained synchronization. Suppose, for example, class MsLunch has two instance fields, c1 and c2, that are never used together. All updates of these fields must be synchronized, but there's no reason to prevent an update of c1 from being interleaved with an update of c2 — and doing so reduces concurrency by creating unnecessary blocking. Instead of using synchronized methods or otherwise using the lock associated with this, we create two objects solely to provide locks.

public class MsLunch {
    private long c1 = 0;
    private long c2 = 0;
    private Object lock1 = new Object();
    private Object lock2 = new Object();

    public void inc1() {
        synchronized(lock1) {
            c1++;
        }
    }

    public void inc2() {
        synchronized(lock2) {
            c2++;
        }
    }
}

Use this idiom with extreme care. You must be absolutely sure that it really is safe to interleave access of the affected fields.

What is Reentrant Synchronization?

Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.

What are the different states of a thread object?

  1. NEW: The thread object is created by the start method has not yet been invoked.
  2. RUNNABLE: A number of threads can be in the RUNNABLE state. The scheduler determine which thread to run.
  3. RUNNING: This thread is running.
  4. BLOCKED / WAITING: The thread is waiting for something such as IO operation to complete.
  5. TERMINATED / DEAD: The thread has complete its execution.

What is thread priority?

The scheduler can be requested to allot more CPU to a thread by increasing the threads priority. Each thread in Java is assigned a default priority 5. This priority can be increased or decreased between the range of 1 and 10.

How can we set thread priority?

Use the setPriority method:

t.setPriority(8);
t.setPriority(Thread.MAX_PRIORITY);
t.setPriority(Thread.MIN_PRIORITY);
t.setPriority(Thread.NORMAL_PRIORITY);

What is the purpose of the ExecutorService?

It is a cool new way to execute a task in the background. You can think of the ExecutorService as similar to a thread pool.

ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
  public void run() {
    ...
  }
});
executorService.shutdown();

What are the different ways to create Executor Services?

// Creates an Executor that use a single worker thread operating off an unbounded queue
ExecutorService executorService1 = Executors.newSingleThreadExecutor();

// Creates a thread pool that reuses a fixed number of threads
// operating off a shared unbounded queue.  At any point, the parameter
// specifies the most threads that will be active processing tasks
ExecutorService executorService2 = Executor.newFixedThreadPool(10);

// Create a thread pool that can schedule commands to run after a given delay
// or to execute periodically
ExecutorService executorService3 = Executor.newScheduleThreadPool(10);

How can we check whether an ExecutorService task executed successfuly?

We can use a Future to check the return value. The Future get method would return null if the task finish successfully.

Future future = executorService1.submit(new Runnable() {
  public void run() {
    ..
  }
});
future.get(); // returns null if the task has finished correctly.

What is a Callable? How can we execute a Callable from ExecutorService?

The Runnable interface's run method has a return type of void. So, it cannot return any result from executing a task. However, a Callable interface's call method has a return type. If you have multiple return values from a task, we can use the Callable interface.

Future futureFromCallable = executorService1.submit(new Callable() {
  public String call() throws Exception {
    return "RESULT";
  }
});
futureFromCallable.get();

How does Java treat static methods and block when the synchronized keyword is used?

Static methods and blocks are synchronized on the class. Instance methods and blocks are synchronized on the instance object.

How can we start one thread only after another thread has finished?

Use the .join method:

thread3.start();
thread2.start();
thread3.join(); // wait for thread3 to complete
thread4.start();

Can we overload the join method?

Yes. The join method can be overloaded to accept a time in milliseconds as a parameter.

thread4.join(2000);

In the above example, the main thread would wait for 2000 milliseconds or the end of execution of thread4 whichever is minimum.

How can a thread yield to another thread?

Use the yield method. It is a static method, so we can invoke it using the Thread class or as an object instance method.

How can a thread sleep for X milliseconds?

Use the sleep method. It is a static method.

What is the purpose of the InterruptedException?

The sleep method can throw a InterruptedException, so we need to handle it.

What is a deadlock?

Let's consider a situation where thread1 is waiting for thread2 (thread1 needs an object whose synchronized code is being executed by thread1), and thread2 is waiting for thread1. This situation is called a deadlock. In a deadlock situation, both of these threads wait for one another forever.

How can we avoid deadlock?

I NEED TO REVISIT THIS.

What are the important methods in Java for inter-thread communication?

wait, notify, and notifyAll

What is the purpose of the wait method?

The wait method is defined in the Object class. This causes the thread to wait until it is notified.

synchronized(thread) {
  thread.start();
  thread.wait();
}

What is the purpose of the notify method?

The notify method is defined in the Object class. This causes the object to notify other waiting threads.

synchronize (this) {
  calculateSumUpToMillion();
  notify();
}

What is the purpose of the notifyAll method?

If more than one thread is waiting for an object, we can notify all the threads by using the notifyAll method.

Example of using wait and notify:

class Calculator extends Thread {
  long sum;
  public void run() {
    synchronized (this) {
      for (int i = 0; i < 10000000; i++) {
        sum += i;
      }
      notify();
    }
  }
}

public class ThreadWaitAndNotify {
  public static void main(String[] args) {
    Calculator thread = new Calculator();
    thread.start();
    synchronized (thread) {
      try {
        thread.wait();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    System.out.println(thread.sum);
  }
}

What is the purpose of the volatile keyword?

Essentially, volatile is used to indicate that a variable's value will be modified by different threads. Declaring a volatile Java variable means:

  1. The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory";
  2. Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.

We say "acts as though" in the second point, because to the programmer at least (and probably in most JVM implementations) there is no actual lock object involved. Here is how synchronized and volatile compare:

Difference between synchronized and volatile
Characteristic Synchronized Volatile
Type of variable Object Object or primitive
Null allowed? No Yes
Can block? Yes No
All cached variables synchronized on access? Yes From Java 5 onwards
When synchronization happens When you explicitly enter/exit a synchronized block Whenever a volatile variable is accessed.
Can be used to combined several operations into an atomic operation? Yes Pre-Java 5, no. Atomic get-set of volatiles possible in Java 5.

What are the differences between the volatile keyword and the synchronized keyword?

Difference between synchronized and volatile
Characteristic Synchronized Volatile
Type of variable Object Object or primitive
Null allowed? No Yes
Can block? Yes No
All cached variables synchronized on access? Yes From Java 5 onwards
When synchronization happens When you explicitly enter/exit a synchronized block Whenever a volatile variable is accessed.
Can be used to combined several operations into an atomic operation? Yes Pre-Java 5, no. Atomic get-set of volatiles possible in Java 5.

In other words, the main differences between synchronized and volatile are:

  1. a primitive variable may be declared volatile (whereas you can't synchronize on a primitive with synchronized);
  2. an access to a volatile variable never has the potential to block: we're only ever doing a simple read or write, so unlike a synchronized block we will never hold on to any lock;
  3. because accessing a volatile variable never holds a lock, it is not suitable for cases where we want to read-update-write as an atomic operation (unless we're prepared to "miss an update");
  4. a volatile variable that is an object reference may be null (because you're effectively synchronizing on the reference, not the actual object).
  5. Attempting to synchronize on a null object will throw a NullPointerException.
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License