Java 8 concurrent programming -- a minimalist introduction

introduce

Process and thread are the methods to realize concurrency. A process is a program instance that runs independently and is directly scheduled and managed by the operating system. Concurrency can also be realized through threads inside the process, which is often used for asynchronous processing or parallel execution of java.

Runable

In Java 8, Runable is a unit that maintains task logic. Runnable is a functional interface, which can be implemented by lambda function. Suppose we want to trigger a virtual task of e-mail.

Runable task () ->{
	system.out.println("Triggering email from:" + Thread.currentThread().getName());
}
task.run();

Execute the above function in the main function, and you will get the following output

Triggering email from: main

You can see that this task is still executed in the main thread, which is not the asynchronous multithreading effect we want.

Thread

The instance of the Thread class takes a Runable as a parameter and generates a new Thread to execute the task in the Runable. Let's update the code above:

Runnable task = () -> {
    System.out.println("Triggering email from: " + Thread.currentThread().getName());
};
Thread thread = new Thread(task);
thread.start();
System.out.println("This is the " + Thread.currentThread().getName() + " thread");

Execute the above code in the main function and you will get the following output:

This is the main Thread
Triggering email from: Thread-0

Now we realize the use of multithreading to complete asynchronous execution. In the case of purely using Thread, we need to manage the creation of all Thread classes, which may be troublesome, and the creation and destruction also have overhead. Java 8 also provides a simple Thread pool class for us to use.

Executors

ExecutorService is introduced as an advanced implementation, which can not only execute tasks asynchronously, but also manage thread pool. Then change the code above

Runnable task = () -> {
    System.out.println("Triggering email from: " + Thread.currentThread().getName());
};
ExecutorService es = Executors.newFixedThreadPool(1);
es.submit(task);
System.out.println("This is the " + Thread.currentThread().getName() + " thread");

Execute the above code in the main function and you will get the following output:

This is the main thread
Triggering email from: pool-1-thread-1

It should be noted that after the above code is executed, the program will not exit. You must manually call shutdown() or shutdown now() to terminate the program.

Callable and Future

Runable can define the execution unit of the task, but it does not return a value (return void). What if you want to return a value? We can use Callable as runable, and get the return value of a Future class instance. When the task is completed, the current thread can load the results into the Future. Therefore, the return is asynchronous and needs to pass Future The get () method blocks and gets the real return value.

Callable<Integer> task = () -> {
    System.out.println("Processing huge amount of data: "+Thread.currentThread().getName());
    TimeUnit.SECONDS.sleep(2);
    return 1000000;
};
ExecutorService es = Executors.newFixedThreadPool(1);
Future<Integer> future = es.submit(task);
Integer result = future.get(); // This method blocks until the content of future is filled
System.out.println(result);
es.shutdown(); // Manually close the thread pool
System.out.println("This is the " + Thread.currentThread().getName() + " thread");

You will get the following output:

Processing huge amount of data: pool-1-thread-1
1000000
This is the main thread

reference resources

Added by chopficaro on Sat, 05 Mar 2022 04:25:06 +0200