Threads

In Java each application has at least one thread, because the JVM creates a main thread to execute the main() method.

The Thread class represents the java thread. Each thread has an identification number, name and priority. You can get the current thread by calling Thread.currentThread().

The Runnable interface represents code that must be executed by thread.

// execute task in thread
new Thread(new Runnable() {
    @Override
    public void run() {
        // code that will be executed in the thread
        System.out.println("2");
    }}).start();

// same as previous, but with lambda
new Thread(() -> System.out.println("2")).start();

The Callable interface represents code that must be executed by thread with result. And Future represents the result of an asynchronous computation. The result can only be obtained using the get() method when the computation is complete. If the result is not ready, the current thread will be blocked waiting for it.

FutureTask<Integer> ft = new FutureTask<>(() -> new Random().nextInt(100));
new Thread(ft).start();
// ... doing something while we don't need result
System.out.println(ft.get()); // print result of the callable task.

thread pools

The ThreadPoolExecutor and ScheduledThreadPoolExecutor classes manage threads and executed tasks to improve performance when executing large numbers of asynchronous tasks, due to reduced per-task invocation overhead. You can configure pools yourself: how many threads to use, how long to keep a thread alive without tasks, etc. Or you can use the utility class Executors that allows to create preconfigured pools.

// creating a cached thread pool by hands
ExecutorService exe = new ThreadPoolExecutor(
       0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
       new SynchronousQueue<Runnable>());
       
// do the same thing with Executors class
ExecutorService exe1 = Executors.newCachedThreadPool();

// pass Runnable task to the executor
exe1.execute(() -> System.out.println("2"));
        
// pass Callable task to the executor
Future<Integer> result = exe1.submit(() -> new Random().nextInt(100));
// ...
result.get(); // get result of Callable task

Executors

method description
callable( runnable ) Converts Runnable task to the Callable task, that return null.
callable(runnable task, result) Converts Runnable task to the Callable task, that return specified result.
defaultThreadFactory() Returns a default thread factory used to create new threads.
newCachedThreadPool() Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available.
newFixedThreadPool(num) Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue.
newScheduledThreadPool(coreNum) Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.
newSingleThreadExecutor() Creates an Executor that uses a single worker thread operating off an unbounded queue.
newSingleThreadScheduledExecutor() Creates a single-threaded executor that can schedule commands to run after a given delay, or to execute periodically.
newWorkStealingPool() Creates a work-stealing thread pool using the number of available processors as its target parallelism level.
unconfigurableExecutorService(executor) Returns an object that delegates all defined ExecutorService methods to the given executor, but not any other methods that might otherwise be accessible using casts.
unconfigurableScheduledExecutorService​(executor) Returns an object that delegates all defined ScheduledExecutorService methods to the given executor, but not any other methods that might otherwise be accessible using casts.