The previous article mainly introduced the concept of multithreading. This article mainly describes eight common ways to create threads in Java:
- Inherit Thread class
- Implement the Runable interface
- Implement the Callable interface
- Thread pool creation
- Anonymous Inner Class
- Using Lambda expressions
- @Async annotation in Spring
- Java8 CompletableFuture
1. create by inheriting Thread
This method is the most primitive method of java
/** * Inherit Thread class * @date 2018 February 22 */ public class TestThread extends Thread{ public TestThread (String name) { super.setName(name); } @Override public void run() { System.out.println("Current thread: "+Thread.currentThread().getName()); } } public class Main { public static void main(String[] args) throws Exception { TestThread testThread = new TestThread("inherit Thread thread "); // Start thread testThread.start(); } }
Usage:
public class Main { public static void main(String[] args) throws Exception { TestThread testThread = new TestThread("inherit Thread thread "); // Start thread testThread.start(); } }
2. create by implementing Runable
The implementation of the Runable interface solves the problem of Java single inheritance on the basis of inheriting the Thread.
/** * Implement the Runnable interface * @date 2018 February 22 */ public class TestRunnable implements Runnable{ @Override public void run() { System.out.println("Current thread: "+Thread.currentThread().getName()); } }
Usage:
public class Main { public static void main(String[] args) throws Exception { // Implement the Runnable interface Thread thread = new Thread(new TestRunnable(),"realization Runnable Thread of"); thread.start(); } }
3.Callable and Future
Java provides the Callable interface, which is an enhanced version of the Runnable interface. The Callable interface also provides a call method that can be used as the thread executor, but the call method is more powerful than the run method:
The call() method has a return value
The call() method can declare to throw an exception (it can only be caught internally in normal run methods)
/** * Implement callable * @date 2018 February 22 */ public class TestCallable implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("Current thread: "+Thread.currentThread().getName()); return 1; } }
Usage:
public class Main { public static void main(String[] args) throws Exception { // Callable and Future FutureTask<Integer> future = new FutureTask<>(new TestCallable()); new Thread(future,"Thread with return value").start(); System.out.println("Return value:"+future.get()); } }
4. thread pool creation thread
Thread pool can solve the problem of rational utilization of resources. The Java JUC package provides the creation of four thread pools, as well as the creation method through the thread pool construction method. This article uses the cacheable thread pool creation method:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Thread pool create thread * @date 2018 February 22 */ public class ExecutorTest { public static void main(String[] args) throws Exception { // 1. cacheable threads reuse threads ExecutorService newCachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 20; i++) { final int tmp = i; newCachedThreadPool.execute(new Runnable() { @Override public void run() { System.out.println("threadName:"+Thread.currentThread().getName()+","+tmp); } }); } } }
5. anonymous inner class creation thread
Anonymous inner classes are different in syntax sugar, and the essence is the same as the second
public class Main { public static void main(String[] args) throws Exception { // Anonymous inner class creation thread new Thread(new Runnable() { @Override public void run() { System.out.println("Current thread: "+Thread.currentThread().getName()); } }, "Anonymous inner class creation thread").start(); } }
6. use Lambda expressions
The use of Lambda expressions is an optimization on the anonymous inner class syntax sugar, which is essentially the same as the second
public class Main { public static void main(String[] args) throws Exception { // Creating threads using Lambda expressions new Thread(() -> System.out.println("Current thread: "+Thread.currentThread().getName()) , "use Lambda Expression creation thread").start(); } }
7. create a thread using @Async
In the Spring framework, the @Async annotation is provided to create threads. Example: if the addUser interface takes 2 seconds and the addMember interface takes 2 seconds, it will take more than 4 seconds if threads are not used. The following is how to optimize the interface loading speed:
@org.springframework.stereotype.Service class Service { /** * Add user simulation delay */ @Async public Future<Integer> addUser(){ try { Thread.sleep(2000); } catch (InterruptedException e) { } System.out.println("addUser Method execution completed!"); return new AsyncResult<Integer>(1); } /** * Add member simulation delay */ @Async public Future<Integer> addMember(){ try { Thread.sleep(2000); } catch (InterruptedException e) { } System.out.println("addMember Method execution completed!"); return new AsyncResult<Integer>(1); } }
Test call:
package com.terry.async; import com.terry.App; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @SpringBootTest(classes = App.class) public class TestAsync { @Autowired private Service service; @Test public void testAsync(){ long start = System.currentTimeMillis(); Future<Integer> member = service.addMember(); Future<Integer> user = service.addUser(); try { System.out.println("result:" + member.get() + "," + user.get()); long end = System.currentTimeMillis(); System.out.println("Interface time:" + (end - start)); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }
Printout
8.java8 completable future create thread
Calling the get method using Callable and Future will cause the main thread to block. Java8's completabilefuture can solve this problem:
import java.util.concurrent.CompletableFuture; /** * Java8 CompletableFuture * @author terry * @version 1.0 * @date 2022/6/2 17:42 */ public class TestCompletableFuture { public static void main(String[] args) throws InterruptedException { System.out.println("Main thread start...."); CompletableFuture<String> completableFuture1 = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } return "Thread running completed, result true"; }); completableFuture1.thenAccept(System.out::println); // If no result is obtained, the main thread can still work while (true) { Thread.sleep(1000); System.out.println("Main thread executing...."); } } }
Print results:
Main thread start.... Main thread executing.... Main thread executing.... Thread running completed, result true Main thread executing.... Main thread executing....