The interviewer asked me: How many ways are there to create threads? I laughed

Preface

Multithreading is basically a must-question item in interviews. Interviewers usually start with simple questions and then dig out your knowledge step by step.

For example, starting from what a thread is, the difference between a thread and a process, there are several ways to create a thread, and there are several states for a thread, and so on.

Next, it will naturally lead to various concurrent packages of thread pool, Lock, Synchronized, and JUC. Then it will lead to the low-level principles of AQS, CAS, JMM, JVM, etc., one by one.

In this section, we will not talk about the others, only that there are several ways to create threads.

Does it feel very simple? Isn't it just that kind of thing?

In fact, it is not. Only if we explain clearly to the interviewer and add our own understanding, can we add points to the interview.

text

Generally speaking, there are the following four methods that we commonly use. The following describes how to use them. Then, how to answer the interviewer's questions during the interview is more appropriate.

1. Inherit the Thread class

By inheriting the Thread class and rewriting its run method, we can create a thread.

  • First define a class to inherit the Thread class and override the run method.
  • Then create this subclass object and call the start method to start the thread.

The interviewer asked me: How many ways are there to create threads?  I laughed

2. Implement Runnable interface

By implementing Runnable and implementing the run method, you can also create a thread.

  • First define a class that implements the Runnable interface and implement the run method.
  • Then create a Runnable implementation class object, and pass it as the target into the constructor of Thread
  • Finally, call the start method to start the thread.

The interviewer asked me: How many ways are there to create threads?  I laughed

3. Implement the Callable interface and implement it in combination with Future

  • First define a Callable implementation class and implement the call method. The call method has a return value.
  • Then pass in the Callable implementation class through the FutureTask construction method.
  • Use FutureTask as the target of the Thread class to create a Thread thread object.
  • Get the execution result of the thread through the get method of FutureTask.

The interviewer asked me: How many ways are there to create threads?  I laughed

4. Create threads through the thread pool

Here we use Executors that comes with the JDK to create thread pool objects.

  • First, define a Runnable implementation class and override the run method.
  • Then create a thread pool with a fixed number of threads.
  • Finally, the thread object is passed in through the execute method of the ExecutorService object.

The interviewer asked me: How many ways are there to create threads?  I laughed

How many ways are there to create threads?

So the question is, I have given examples of four ways to create threads. Does it mean that there are only four?

Let's first look at an explanation of the Thread class in the JDK source code, as shown in the figure below.

The interviewer asked me: How many ways are there to create threads?  I laughed

There are two ways to create a new thread of execution

Translation: There are two ways to create a new thread of execution

The two methods mentioned here correspond to the first two methods we introduced.

However, we will find that these two methods will eventually call the Thread.start method, and the start method will eventually call the run method.

The difference is that in the way of implementing the Runnable interface, the run method of the Thread class is called. Let's take a look at its source code,

The interviewer asked me: How many ways are there to create threads?  I laughed

In this way, the created Runnable implementation class object will be assigned to the target, and the target's run method will be run.

Looking at the way to inherit the Thread class, we also need to call the start method of Thread to start the thread. Since the subclass overrides the run method of the Thread class, the run method of this subclass is finally executed.

Therefore, we can also say the same. In essence, there is only one way to create a thread, which is to construct a Thread class (its subclass can also be considered a Thread class).

There are two ways to construct the Thread class, one is to inherit the Thread class, and the other is to implement the Runnable interface. It will eventually create objects of the Thread class (or its subclasses).

Let's look at the way to implement Callable, combining Future and FutureTask. It can be found that the Thread class is finally constructed through new Thread(task).

Finally, in the thread pool, we actually hand the task of creating and managing threads to the thread pool. The thread creation is created through the thread factory class DefaultThreadFactory (you can also customize the factory class). Let's look at the specific implementation of this factory class.

The interviewer asked me: How many ways are there to create threads?  I laughed

It will set some default values ​​for the thread, such as thread name, thread priority, thread group, whether it is a daemon thread, etc. Finally, the thread is created through the new Thread() method.

Therefore, in summary. When answering this question, we can say that there is essentially only one way to create a thread, which is to construct a Thread class . (This conclusion borrows from Java Concurrent Programming 78 Lectures-Xu Longxi)

personal idea

However, here I want to raise some questions about this conclusion (if you have different opinions, you can leave a message at the end of the article~). . .

Personally, if you want to say that there are 1, 2, 3, and 4 types, it is actually okay. The important thing is that you must be able to state your basis, and tell their respective differences and commonalities. Speak well, let the interviewer nod to you frequently. .

It is a bit far-fetched to say that there is only one way to create threads by constructing the Thread class. Because, no matter you start from any means, if you want to create a thread, you will definitely construct the Thread class in the end. (Including the above methods, even through reflection, isn't it also newInstance in the end).

Then, if we follow this logic, I can say that no matter how to create any object, there is only one way to construct the Object class. This conclusion seems a bit too boring, because this is a very correct nonsense.

Take ArrayList as an example. I ask you how to create ArrayList in several ways. 80% of you will tell me to show off what you know,

  1. Through the construction method,List list = new ArrayList();
  2. By  Arrays.asList("a", "b");
  3. Through the Stream API provided by Java8, such as List list = Stream.of("a", "b").collect(Collectors.toList());
  4. Through the guava third-party jar package,List list3 = Lists.newArrayList("a", "b");

Wait, only four are listed above. Now, I tell you that there is only one way to create an ArrayList, which is to construct an ArrayList class. You are not crazy.

It's like, I asked you how many ways to go from Beijing to Shanghai.

You say that you can take a car, train, train, high-speed rail, or plane.

That's not right. Both high-speed trains and high-speed trains belong to trains, cars and trains belong to cars, and cars and planes belong to means of transportation. In this way, there is only one way, which is to take transportation.

This is not right. I don’t need to take transportation. Can’t I walk there? (I can teleport with my eyes, just your skin~).

The final conclusion is that there is only one way, that is, you can go to Shanghai. This, this, this is what a conclusion. . .

So I personally think that there is only one way to create threads.

A good technical essay, almost written into an argumentative essay by me. . .

The benevolent sees the benevolent and the wise sees the wisdom.

Finally, let's take a look at a very interesting topic I saw from the Internet.

Interesting topic

Question: A class that implements the Runnable interface will execute the default run method, then judge that the target is not empty, and finally execute the run method implemented in the Runnable interface. Inheriting the Thread class will execute the rewritten run method. So, now I both inherit the Thread class and implement the Runnable interface. The following program, what should be output?

public class TestThread {
    public static void main(String[] args) {
        new Thread(()-> System.out.println("runnable")){
            @Override
            public void run() {
                System.out.println("Thread run");
            }
        }.start();
    }
}

It may seem daunting at first glance, what kind of operation is this.

In fact, if we disassemble the above code, we will know that this is a subclass object that inherits the parent class of Thread, and overrides the run method of the parent class. Then, in the parent object Thread, an implementation class of the Runnable interface is passed in the construction method to implement the run method.

Now that the start method is executed, it will inevitably look for the run method in the subclass first, and will execute it directly if it finds it. The run method of the parent class will not be executed, so the result is: Thread run.

If it is assumed that the subclass does not implement the run method, it will look for the run method in the parent class, and the run method of the parent class will determine whether there is a Runnable passed (that is, whether the target is empty), and now the target is not empty, so The target.run method will be executed, and the result will be printed: runnable.

So, the code above looks complicated, but it's actually very simple. Looking at the essence through the phenomenon, we will find that it is nothing more than investigating the parent-child inheritance relationship of the class, and the subclass overrides the method of the parent class will give priority to the method of the subclass override.

Combined with threads, if you are not familiar with the thread operating mechanism, you may be confused.

Guess you like

Origin blog.51cto.com/14957073/2544445
Recommended