1. Java Concurrency from docs.oracle.com
Computer users take it for granted that their systems can do more than one thing at a time. They assume that they can continue to work in a word processor, while other applications download files, manage the print queue, and stream audio. Even a single application is often expected to do more than one thing at a time. For example, that streaming audio application must simultaneously read the digital audio off the network, decompress it, manage playback, and update its display. Even the word processor should always be ready to respond to keyboard and mouse events, no matter how busy it is reformatting text or updating the display. Software that can do such things is known as concurrent software.
The Java platform is designed from the ground up to support concurrent programming, with basic concurrency support in the Java programming language and the Java class libraries. Since version 5.0, the Java platform has also included high-level concurrency APIs. This lesson introduces the platform's basic concurrency support and summarizes some of the high-level APIs in the java.util.concurrent packages.

Processes and Threads

In concurrent programming, there are two basic units of execution: processes and threads. In the Java programming language, concurrent programming is mostly concerned with threads. However, processes are also important.
A computer system normally has many active processes and threads. This is true even in systems that only have a single execution core, and thus only have one thread actually executing at any given moment. Processing time for a single core is shared among processes and threads through an OS feature called time slicing.
It's becoming more and more common for computer systems to have multiple processors or processors with multiple execution cores. This greatly enhances a system's capacity for concurrent execution of processes and threads — but concurrency is possible even on simple systems, without multiple processors or execution cores.

Processes

A process has a self-contained execution environment. A process generally has a complete, private set of basic run-time resources; in particular, each process has its own memory space.
Processes are often seen as synonymous with programs or applications. However, what the user sees as a single application may in fact be a set of cooperating processes. To facilitate communication between processes, most operating systems support Inter Process Communication (IPC) resources, such as pipes and sockets. IPC is used not just for communication between processes on the same system, but processes on different systems.
Most implementations of the Java virtual machine run as a single process. A Java application can create additional processes using a ProcessBuilder object. Multiprocess applications are beyond the scope of this lesson.

Threads

Threads are sometimes called lightweight processes. Both processes and threads provide an execution environment, but creating a new thread requires fewer resources than creating a new process.
Threads exist within a process — every process has at least one. Threads share the process's resources, including memory and open files. This makes for efficient, but potentially problematic, communication.
Multithreaded execution is an essential feature of the Java platform. Every application has at least one thread — or several, if you count "system" threads that do things like memory management and signal handling. But from the application programmer's point of view, you start with just one thread, called the main thread. This thread has the ability to create additional threads, as we'll demonstrate in the next section.

Thread Objects


Each thread is associated with an instance of the class Thread. There are two basic strategies for using Thread objects to create a concurrent application.
  • To directly control thread creation and management, simply instantiate Thread each time the application needs to initiate an asynchronous task (implements Runnable or  Subclass Thread).
  • To abstract thread management from the rest of your application, pass the application's tasks to an executor.
This section documents the use of Thread objects. Executors are discussed with other high-level concurrency objects.

Executors

In all of the previous examples, there's a close connection between the task being done by a new thread, as defined by its Runnable object, and the thread itself, as defined by a Thread object. This works well for small applications, but in large-scale applications, it makes sense to separate thread management and creation from the rest of the application. Objects that encapsulate these functions are known as executors. The following subsections describe executors in detail.
  • Executor Interfaces define the three executor object types.
  • Thread Pools are the most common kind of executor implementation.
  • Fork/Join is a framework (new in JDK 7) for taking advantage of multiple processors.
The java.util.concurrent package defines three executor interfaces:
  • 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.
Typically, variables that refer to executor objects are declared as one of these three interface types, not with an executor class type.
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 replace
(new Thread(r)).start();
with

e.execute(r);

2. ExecutorService

by Jakob Jenkov from jenkov.com
The java.util.concurrent.ExecutorService interface represents an asynchronous execution mechanism which is capable of executing tasks in the background. An ExecutorService is thus very similar to a thread pool. In fact, the implementation of ExecutorService present in the java.util.concurrent package is a thread pool implementation.

Here is a simple Java ExectorService example:
ExecutorService executorService = Executors.newFixedThreadPool(10);

executorService.execute(new Runnable() {
    public void run() {
        System.out.println("Asynchronous task");
    }
});

executorService.shutdown();
First an ExecutorService is created using the newFixedThreadPool() factory method. This creates a thread pool with 10 threads executing tasks.
Second, an anonymous implementation of the Runnable interface is passed to the execute() method. This causes the Runnable to be executed by one of the threads in the ExecutorService.

Here is a diagram illustrating a thread delegating a task to an ExecutorService for asynchronous execution:
A thread delegating a task to an ExecutorService for asynchronous execution.

Once the thread has delegated the task to the ExecutorService, the thread continues its own execution independent of the execution of that task.

ExecutorService Implementations
Since ExecutorService is an interface, you need to its implementations in order to make any use of it. The ExecutorService has the following implementation in the java.util.concurrent package:
Creating an ExecutorService
How you create an ExecutorService depends on the implementation you use. However, you can use the Executors factory class to create ExecutorService instances too. Here are a few examples of creating an ExecutorService:
ExecutorService executorService1 = Executors.newSingleThreadExecutor();

ExecutorService executorService2 = Executors.newFixedThreadPool(10);

ExecutorService executorService3 = Executors.newScheduledThreadPool(10);

ExecutorService Usage
There are a few different ways to delegate tasks for execution to an ExecutorService:
  • execute(Runnable)
  • submit(Runnable)
  • submit(Callable)
  • invokeAny(...)
  • invokeAll(...)
I will take a look at each of these methods in the following sections.

- execute(Runnable)
The execute(Runnable) method takes a java.lang.Runnable object, and executes it asynchronously. Here is an example of executing a Runnable with an ExecutorService:
ExecutorService executorService = Executors.newSingleThreadExecutor();

executorService.execute(new Runnable() {
    public void run() {
        System.out.println("Asynchronous task");
    }
});

executorService.shutdown();
There is no way of obtaining the result of the executed Runnable, if necessary. You will have to use a Callable for that (explained in the following sections).

- submit(Runnable)
The submit(Runnable) method also takes a Runnable implementation, but returns a Future object. This Future object can be used to check if the Runnable as finished executing.
Here is a ExecutorService submit() example:
Future future = executorService.submit(new Runnable() {
    public void run() {
        System.out.println("Asynchronous task");
    }
});

future.get();  //returns null if the task has finished correctly.

- submit(Callable)
The submit(Callable) method is similar to the submit(Runnable) method except for the type of parameter it takes. The Callable instance is very similar to a Runnable except that its call() method can return a result. The Runnable.run() method cannot return a result.
The Callable's result can be obtained via the Future object returned by the submit(Callable) method. Here is an ExecutorService Callable example:
Future future = executorService.submit(new Callable(){
    public Object call() throws Exception {
        System.out.println("Asynchronous Callable");
        return "Callable Result";
    }
});

System.out.println("future.get() = " + future.get());
The above code example will output this:
Asynchronous Callable
future.get() = Callable Result

- invokeAny()
The invokeAny() method takes a collection of Callable objects, or subinterfaces of Callable. Invoking this method does not return a Future, but returns the result of one of the Callable objects. You have no guarantee about which of the Callable's results you get. Just one of the ones that finish.
If one of the tasks complete (or throws an exception), the rest of the Callable's are cancelled.
Here is a code example:
ExecutorService executorService = Executors.newSingleThreadExecutor();

Set<Callable<String>> callables = new HashSet<Callable<String>>();

callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 1";
    }
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 2";
    }
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 3";
    }
});

String result = executorService.invokeAny(callables);

System.out.println("result = " + result);

executorService.shutdown();
This code example will print out the object returned by one of the Callable's in the given collection. I have tried running it a few times, and the result changes. Sometimes it is "Task 1", sometimes "Task 2" etc.

- invokeAll()
The invokeAll() method invokes all of the Callable objects you pass to it in the collection passed as parameter. The invokeAll() returns a list of Future objects via which you can obtain the results of the executions of each Callable.
Keep in mind that a task might finish due to an exception, so it may not have "succeeded". There is no way on a Future to tell the difference.
Here is a code example:
ExecutorService executorService = Executors.newSingleThreadExecutor();

Set<Callable<String>> callables = new HashSet<Callable<String>>();

callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 1";
    }
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 2";
    }
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 3";
    }
});

List<Future<String>> futures = executorService.invokeAll(callables);

for(Future<String> future : futures){
    System.out.println("future.get = " + future.get());
}

executorService.shutdown();




ExecutorService Shutdown
When you are done using the ExecutorService you should shut it down, so the threads do not keep running.
For instance, if your application is started via a main() method and your main thread exits your application, the application will keep running if you have an active ExexutorService in your application. The active threads inside this ExecutorService prevents the JVM from shutting down.
To terminate the threads inside the ExecutorService you call its shutdown() method. The ExecutorService will not shut down immediately, but it will no longer accept new tasks, and once all threads have finished current tasks, the ExecutorService shuts down. All tasks submitted to the ExecutorService before shutdown() is called, are executed.
If you want to shut down the ExecutorService immediately, you can call the shutdownNow() method. This will attempt to stop all executing tasks right away, and skips all submitted but non-processed tasks. There are no guarantees given about the executing tasks. Perhaps they stop, perhaps the execute until the end. It is a best effort attempt. 


3. Java ExecutorService Example – Tutorial

by Katerina Zamani - javacodegeeks.com
ExecutorService is an interface that extends Executor class and represents an asynchronous execution. It provides us mechanisms to manage the end and detect progress of the asynchronous tasks.
In this example we are going to see some basic functionalities of ExecutorService, as well as handle the Future object, the result of asynchronous computation.

3.1. Create the Runnable

We are going to create a Runnable that is intended to be executed by the ExecutorService. Create a java class named myThread and paste the following code.
myThread.java:
package com.javacodegeeks.core.concurrency.executorservicetest;

public class MyThread implements Runnable {

private String myName;
private int count;
private final long timeSleep;

MyThread(String name, int newcount, long newtimeSleep) {
this.myName = name;
   this.count = newcount;
   this.timeSleep = newtimeSleep;
}

@Override
public void run() {
// TODO Auto-generated method stub

int sum = 0;
   for (int i = 1; i <= this.count; i++) {
    sum = sum + i;
   }
   System.out.println(myName + " thread has sum = " + sum +
    " and is going to sleep for " + timeSleep);
   try {
Thread.sleep(this.timeSleep);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

The functionality of the Runnable is very simple. It computes a sum from the giving argument and it sleeps for a specified time.

3.2. Code the ExecutorService

In this example we will use a factor method of ExecutorService that creates a thread pool of fixed number of threads. For this reason, newFixedThreadPool() method is used where we specify the number of threads in the pool. To execute the thread, we can use either execute() method or submit(), where both of them take Runnable as a parameter. execute() method is depending on the implementation of the Executor class and may perform the Runnable in a new thread, in a pooled thread, or in the calling thread. submit() method extends execute(), by returning a Future that represents the submitting task.
The Future can be used to indicate the termination of execution of the thread. For instance, get() method waits for the completion of the computation. If the returning value is null, the task has finished correctly. Otherwise, cancel() method can be called in order to end the execution of this task. It is worth to mention that for bulk or a collection of thread execution, invokeAll() and invokeAny() are used respectively, although there are not used in this example.
To close down the ExecutorService, there are many methods that can be used. In our example we use shutdown() method, in which the submitted tasks are executed before the shutting down but new tasks can not be accepted. Another approach is shutdownNow() method, which stops the executing tasks, pause the waiting ones and returns the list of the awaiting ones. Moreover, awaitTermination() can be used in order to wait until all threads are terminated.
For further understanding of the main functionality of ExecutorService, have a look at the code below. Create ExecutorServiceTest.java file and paste the following.
ExecutorServiceTest.java:
package com.javacodegeeks.core.concurrency.executorservicetest;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class ExecutorServiceTest {

private static Future taskTwo = null;
private static Future taskThree = null;
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(2);
  
// execute the Runnable
   Runnable taskOne = new MyThread("TaskOne", 2, 100);
   executor.execute(taskOne);
   for(int i = 0; i < 2; i++) {
    // if this task is not created or is canceled or is completed
if ((taskTwo == null) || (taskTwo.isDone()) || (taskTwo.isCancelled())) {
// submit a task and return a Future
taskTwo = executor.submit(new MyThread("TaskTwo", 4, 200));
}
if ((taskThree == null) || (taskThree.isDone()) || (taskThree.isCancelled())) {
taskThree = executor.submit(new MyThread("TaskThree", 5, 100));
}
// if null the task has finished
if(taskTwo.get() == null) {
System.out.println(i+1 + ") TaskTwo terminated successfully");
} else {
// if it doesn't finished, cancel it
taskTwo.cancel(true);
}
if(taskThree.get() == null) {
System.out.println(i+1 + ") TaskThree terminated successfully");
} else {
taskThree.cancel(true);
}
   }
   executor.shutdown();
   System.out.println("-----------------------");
   // wait until all tasks are finished
   executor.awaitTermination(1, TimeUnit.SECONDS);
   System.out.println("All tasks are finished!");
}

}

Now you can see the output of the execution.
Output:
TaskOne thread has sum = 3 and is going to sleep for 100
TaskTwo thread has sum = 10 and is going to sleep for 200
TaskThree thread has sum = 15 and is going to sleep for 100
1) TaskTwo terminated successfully
1) TaskThree terminated successfully
TaskTwo thread has sum = 10 and is going to sleep for 200
TaskThree thread has sum = 15 and is going to sleep for 100
2) TaskTwo terminated successfully
2) TaskThree terminated successfully
-----------------------
All tasks are finished!

Download the source code

This was an example of ExecutorService in Java. Download the source code of this example: ExecutorServiceTest.zip or ExecutorServiceTest.zip


Reference documents
Java Concurrency in Depth (Part 1)
Java Concurrency in Depth (Part 2)
Java Concurrency in Depth (Part 3)
Java Concurrency in Depth (Part 4)
Java Concurrency in Depth (Part 5)
Java Concurrency in Depth (Part 6)
Java Concurrency in Depth (Part 7)    
java-multithreading-concurrency-interview
Java Concurrency Concepts
Java concurrency (multi-threading) - Tutorial