Eight ways to create Java threads, how many do you know?

Keywords: Java Spring Programming Lambda

Author: Tang Tong

brief introduction

Creating threads is the most basic operation in multithreaded programming. Tong Ge summed up that there are about eight ways to create threads, you know?

1. Inherit the Thread class and override the run() method

public class CreatingThread01 extends Thread {
 @Override
 public void run() {
 System.out.println(getName() + " is running");
 }
 public static void main(String[] args) {
 new CreatingThread01().start();
 new CreatingThread01().start();
 new CreatingThread01().start();
 new CreatingThread01().start();
 }
}

The disadvantage of inheriting the Thread class and overwriting the run() method is that a class can only inherit one parent class, which cannot be used if the class itself has inherited other classes.

2. Implementing Runnable Interface

public class CreatingThread02 implements Runnable {
 @Override
 public void run() {
 System.out.println(Thread.currentThread().getName() + " is running");
 }
 public static void main(String[] args) {
 new Thread(new CreatingThread02()).start();
 new Thread(new CreatingThread02()).start();
 new Thread(new CreatingThread02()).start();
 new Thread(new CreatingThread02()).start();
 }
}

The advantage of implementing Runnable interface is that a class can implement multiple interfaces without affecting its inheritance system.

3. Anonymous inner classes

public class CreatingThread03 {
 public static void main(String[] args) {
 //Thread anonymous class, rewriting Thread's run() method
 new Thread() {
 @Override
 public void run() {
 System.out.println(getName() + " is running");
 }
 }.start();
 //Runnable anonymous class to implement its run() method
 new Thread(new Runnable() {
 @Override
 public void run() {
 System.out.println(Thread.currentThread().getName() + " is running");
 }
 }).start();
 //Ibid., using lambda expression functional programming
 new Thread(()->{
 System.out.println(Thread.currentThread().getName() + " is running");
 }).start();
 }
}

The way to use anonymous classes is to rewrite Thread's run() method, pass in Runnable's anonymous classes, and lambda's method. Now the third (java 8+) is generally used, which is simple and fast.

4. Implementing Callabe Interface

public class CreatingThread04 implements Callable<Long> {
 @Override
 public Long call() throws Exception {
 Thread.sleep(2000);
 System.out.println(Thread.currentThread().getId() + " is running");
 return Thread.currentThread().getId();
 }
 public static void main(String[] args) throws ExecutionException, InterruptedException {
 FutureTask<Long> task = new FutureTask<>(new CreatingThread04());
 new Thread(task).start();
 System.out.println("Waiting for the task to be completed");
 Long result = task.get();
 System.out.println("Task results:" + result);
 }
}

Implementing the Callabe interface allows you to get the results of thread execution, and FutureTask actually implements the Runnable interface.

5. Timer (java.util.Timer)

public class CreatingThread05 {
 public static void main(String[] args) {
 Timer timer = new Timer();
 //Execute every 1 second
        timer.schedule(new TimerTask() {
 @Override
 public void run() {
 System.out.println(Thread.currentThread().getName() + " is running");
 }
 }, 0 , 1000);
 }
}

Timer java.util.Timer can quickly implement timing tasks. TimerTask actually implements the Runnable interface.

6. Thread pool

public class CreatingThread06 {
 public static void main(String[] args) {
 ExecutorService threadPool = Executors.newFixedThreadPool(5);
 for (int i = 0; i < 100; i++) {
            threadPool.execute(()-> System.out.println(Thread.currentThread().getName() + " is running"));
 }
 }
}

Thread pool can reuse threads and save system resources.

7. Parallel Computing (Java 8+)

public class CreatingThread07 {
 public static void main(String[] args) {
 List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
 //Serial, printing result 12345
        list.stream().forEach(System.out::print);
 System.out.println();
 //Parallel, print results randomly, such as 35214
        list.parallelStream().forEach(System.out::print);
 }
}

Parallel computing can improve the efficiency of program running and multi-threaded parallel execution.

8.Spring Asynchronous Method

First, the springboot startup class is annotated with the @EnableAsync annotation (@EnableAsync is supported by spring, so it's convenient to use springboot for example).

@SpringBootApplication
@EnableAsync
public class Application {
 public static void main(String[] args) {
 SpringApplication.run(Application.class, args);
 }
}

Second, add the @Async annotation to the method.

@Service
public class CreatingThread08Service {
 @Async
 public void call() {
 System.out.println(Thread.currentThread().getName() + " is running");
 }
}

Then, the test case is directly identical to the general Service approach.

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class CreatingThread08Test {
 @Autowired
 private CreatingThread08Service creatingThread08Service;
 @Test
 public void test() {
        creatingThread08Service.call();
        creatingThread08Service.call();
        creatingThread08Service.call();
        creatingThread08Service.call();
 }
}

The results are as follows:

task-3 is running
task-2 is running
task-1 is running
task-4 is running

You can see that the threads used for each method execution are different.

The Spring asynchronous method can be said to be quite convenient. It is suitable for some methods which are logically unrelated and suitable for asynchronous calls, such as the function of sending short messages.

Welcome everyone to pay attention to my public giant [programmer chasing wind], articles will be updated in it, collated information will also be placed in it.

summary

(1) Inheriting the Thread class and overwriting the run() method;

(2) Implementing Runnable interface;

(3) Anonymous internal classes;

(4) Implementing Callabe interface;

(5) Timer (java.util.Timer);

(6) Thread pool;

(7) Parallel computing (Java 8+);

(8) Spring asynchronous method;

welfare

In fact, there are two ways to create threads. One is to inherit the Thread class and override its run() method. The other is to implement the run() method of Runnable interface. What is the relationship between them?

See the following example, inheriting Thread and implementing the Runnable interface at the same time. What should be output?

public class CreatingThread09 {
 public static void main(String[] args) {
 new Thread(()-> {
 System.out.println("Runnable: " + Thread.currentThread().getName());
 }) {
 @Override
 public void run() {
 System.out.println("Thread: " + getName());
 }
 }.start();
 }
}

At this point, we need to look at the source code of the Thread class:

public class Thread implements Runnable {
 //Thread maintains an instance of Runnable
 private Runnable target;
 public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
 }
 public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
 }
 private void init(ThreadGroup g, Runnable target, String name,
 long stackSize, AccessControlContext acc,
 boolean inheritThreadLocals) {
 // ...
 //Runnable passed in from the constructor is assigned to target
 this.target = target;
 // ...
 }
 @Override
 public void run() {
 //The default run() method of Thread executes the run() method of target if the target is not empty
 if (target != null) {
            target.run();
 }
 }
}

Is it a pleasant sight to see here? Since the example above inherits Thread and implements the Runnable interface at the same time, according to the source code, it is actually equivalent to rewriting Thread's run() method, which in fact has nothing to do with target.

So the output of the above example is Thread:Thread-0, which only outputs the contents of the run() method that overrides Thread.

Last

Welcome everyone to exchange, like the article remember to point a compliment yo, thank you for your support!


Posted by Honor on Wed, 09 Oct 2019 06:48:43 -0700