preface

Multithreading is basically a must in the interview, the interviewer will usually start from simple questions to ask, and then step by step to explore your knowledge.

For example, start with what a thread is, the difference between a thread and a process, how many ways to create a thread, how many states a thread has, and so on.

Thread pooling, Lock, Synchronized, JUC, etc. Then it will lead to AQS, CAS, JMM, JVM and other partial underlying principles, a ring ring.

We won’t talk about anything else in this section except that there are several ways to create threads.

Doesn’t it feel very simple, just the blah blah blah blah.

In fact, it is not, only we explain clearly to the interviewer, and add our own understanding, in order to score points in the interview.

The body of the

Generally speaking, we are more commonly used in the following four ways, the following is to introduce their use methods. Then, how to answer the interviewer’s questions in the interview is appropriate.

Inherit the Thread class

We can create a Thread by inheriting the Thread class and overriding its run method.

  • Start by defining a class that inherits Thread and overrides the run method.
  • The subclass object is then created and the start method is called to start the thread.

2. Implement Runnable interface

You can also create a thread by implementing Runnable and implementing the run method.

  • Start by defining a class that implements the Runnable interface and implements the Run method.
  • We then create the Runnable implementation class object and pass it as a target in the Thread constructor
  • Finally, the start method is called to start the thread.

3. Implement Callable interface and Future implementation

  • Start by defining a Callable implementation class that implements the Call method. The call method returns a value.
  • The Callable implementation class is then passed in through the FutureTask constructor.
  • Create a Thread object using FutureTask as the target of the Thread class.
  • The thread execution results are obtained through FutureTask’s GET method.

Create a thread from a thread pool

Use the JDK Executors to create the thread pool object.

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

How many ways are there to create a thread?

So the question is, are there four ways to create a thread that I’m giving you here?

Let’s take a look at the JDK source code for Thread, as shown below.

There are two ways to create a new thread of execution

There are two ways to create a new thread of execution

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

In both cases, however, we’ll see that we end up calling thread. start, which ends up calling run.

The difference is that the Runnable interface is implemented in a way that calls the Run method of the Thread class. Let’s take a look at the source code,

This way, the created Runnable implementation object is assigned to Target and target’s run method is run.

To inherit the Thread class, we also need to call the Thread start method to start the Thread. Because a subclass overrides the Run method of Thread, the subclass’s run method ends up being executed.

So, we can say the same thing. In essence, there is only one way to create a Thread, and that 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, the other is to implement the Runnable interface. They all end up creating objects of the Thread class (or its subclasses).

Let’s look at how Callable is implemented, combined with Future and FutureTask. As you can see, the Thread class is eventually constructed as a new Thread(Task).

Finally, in a thread pool, we are essentially leaving the task of creating and managing threads to the thread pool. Threads are created using the thread factory class DefaultThreadFactory (you can also customize the factory class). Let’s look at the concrete implementation of this factory class.

It sets default values for the thread, such as thread name, thread priority, thread group, whether it is a daemon thread, etc. Finally, threads are created using new Thread().

So, to sum up. In answering this question, we can say that there is essentially only one way to create a Thread, and that is to construct a Thread class. (This conclusion comes from the Java Concurrency column.)

Personal ideas

However, I would like to question this conclusion a little bit here…

In my opinion, if you say there are 1, 2, 3, 4, it’s actually ok. The important thing is to be able to state your evidence, the differences and similarities between them. Speak well enough to make your interviewer nod at you.

I think it’s a stretch to say that there is only one way to create a Thread. Because any way you create a Thread, you end up building the Thread class. (Including the above methods, even through reflection, is not the final newInstance).

Then, if I follow this logic, I can say that there is only one way to create any Object, that is, to construct this Object class. This conclusion seems a little too boring, because it’s a very true nonsense.

In the case of an ArrayList, I asked you how many ways you can create an ArrayList. You probably want to brag about how much you know, and say,

  1. By constructing it,List list = new ArrayList();
  2. throughArrays.asList("a", "b");
  3. The Stream API provided through Java8, for exampleList list = Stream.of("a", "b").collect(Collectors.toList());
  4. With the Guava third-party JAR package,List list3 = Lists.newArrayList("a", "b");

Wait, that’s just four of them. Now, I’m telling you there’s only one way to create an ArrayList, which is to create an ArrayList class, and you’re freaking out.

This is like asking you how many ways to get from Beijing to Shanghai.

You said you could take a car, a train, a bullet train, a high-speed train, a plane.

That’s not true. Bullet trains and high-speed trains belong to trains. Cars and trains belong to cars. So there’s only one way, which is by transportation.

This is not right, I don’t have to take transportation, I can walk there (I can also plug the eye transmission, you skin ~).

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

So in my opinion, saying there is only one way to create a thread is a bit inappropriate.

A good technical article, almost was written by me argumentative…

Well, that’s a matter of opinion.

Finally, let’s take a look at a very interesting topic that I read on the Internet.

Interesting topic

Q: A class that implements the Runnable interface executes the default run method, determines that target is not null, and then executes the run method implemented in the Runnable interface. Inheriting Thread executes the overridden run method. So, now that I inherit Thread and implement the Runnable interface, what should the following program output?

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

It may seem confusing at first, what is this operation.

This is a subclass that inherits Thread and overrides the run method. The parent Thread is then passed an implementation class of the Runnable interface that implements the Run method in the constructor.

If the start method is executed, the subclass must first look for the run method, and then execute it directly. The result is Thread run.

If a subclass does not implement a run method, then it looks for the run method in the parent class, and the parent class’s run method determines if a Runnable was passed. Now target is not empty, so target.run is executed. That is, the print result: runnable.

So, the code above looks complicated, but it’s actually quite simple. If we look at the nature of the phenomenon, we will find that it is nothing more than examining the parent-child inheritance relationship of a class. If a subclass overrides the parent class’s method, it will take precedence over the method overridden by the subclass.

When combined with threads, if you are not familiar with how threads work, you are likely to be confused.