🎓 Do your best and obey the destiny. I am a postgraduate student in Southeast University and a summer intern in Java background development in Ctrip. I love fitness and basketball, and I am willing to share what I have seen and gained related to technology. I follow the public account @flying Veal and get the update of the article as soon as possible

🎁 This article has been included in the “CS-Wiki” Gitee official recommended project, has accumulated 1.7K + STAR, is committed to creating a perfect back-end knowledge system, in the road of technology to avoid detours, welcome friends to come to exchange and study

🍉 If you do not have a good project, you can refer to a project I wrote “Open source community system Echo” Gitee official recommended project, so far has accumulated 700+ STAR, SpringBoot + MyBatis + Redis + Kafka + Elasticsearch + Spring Security +… And provide detailed development documents and supporting tutorials. Echo Echo Echo Echo Echo Echo Echo Echo Echo Echo Echo Echo Echo Echo


I was not willing to write basic knowledge at first. After all, people may not be willing to read such simple knowledge, and it is easy to write popular, but it is still good to comb through it and get some harvest. For example, I saw the run method rewritten by Thread class. You can see why Runnable tasks can be separated from threads themselves.

Three ways to create a thread

Thread, which is also the name of the Java class for threads, is included in the java.lang package.

Note that it implements the Runnable interface, as explained below.

Thread and task merging – Inherits the Thread class directly

Threads are created to perform specific tasks, and the tasks or tasks a Thread needs to perform are defined in the Run method of the Thread class.

Where does this run method come from?

In fact, it is not the Thread class itself. Thread implements the Runnable interface, where the run method is defined as an abstract method, and Thread implements it.

So it might be easier to call this Runnable interface a task class.

Here is an example of creating a custom Thread Thread1 by integrating the Thread class:

// Custom thread objects
class Thread1 extends Thread {
    @Override
	public void run(a) {
		// The task that the thread needs to perform. }}// Create a thread object
Thread1 t1 = new Thread1();
Copy the code

Here, the Thread class provides a constructor that specifies a name for a Thread:

So, we can go like this:

// Create a thread object
Thread1 t1 = new Thread1("t1");
Copy the code

This way, when the console prints, it is clear at a glance which thread is producing the output.

Of course, in general, we write code with a simplified version of an anonymous inner class like this:

// Create a thread object
Thread t1 = new Thread("t1") {
	@Override
	// The run method implements the task to be executed
	public void run(a) {
		// The task that the thread needs to perform. }};Copy the code

Thread and task separation – Thread + implements the Runnable interface

If we have multiple threads, all of which are doing the same thing, wouldn’t we be writing a lot of repetitive code?

Therefore, we consider separating the tasks performed by the thread from the thread itself.

class MyRunnable implements Runnable {
    @Override
    public void run(a) {
        // The task that the thread needs to perform. }}// Create a task object
MyRunnable runnable = new MyRunnable();
// Create a thread object
Thread t2 = new Thread(runnable);
Copy the code

In addition to avoiding duplicate code, using the Runnable interface provides more flexibility than using method 1’s single-inherited Thread class. After all, a class can only inherit from one parent class, and the first method cannot be used if the class already inherits from another class. In addition, this way, it is easier to integrate with advanced apis such as thread pools.

Therefore, it is generally recommended to use this method to create threads. That is, working directly on thread objects is not recommended, but on task objects.

The code above uses a simplified version of the anonymous inner class as follows:

// Create a task object
Runnable runnable = new Runnable() {
    public void run(a){
        // The task to be performed. }};// Create a thread object
Thread t2 = new Thread(runnable);
Copy the code

We can also give it a thread name:

Thread t2 = new Thread(runnable, "t2");
Copy the code

The constructors for the two threads are shown below:

Thread constructors all call init. What does this method do? Let’s click inside to see:

It passes the Runnable object passed in by the constructor to a member variable target.

A target is a Runnable object defined in the Thread class that represents What will be run.

The existence of this variable is why we can separate tasks (Runnable) from threads themselves (Thread). Take a look at this code:

Yes, this is the run method implemented by Thread by default.

When using the first method to create a Thread, we define a Thread subclass and override the run method of its parent class, so that the run method implemented by the parent class is not executed, but executes the run method of our custom subclass.

When we created the Thread using the second method, we did not override the run method in the Thread subclass, so the default run method implemented by the parent class was executed.

If taget! = null, which means that if a Runnable object is passed into the Thread constructor, the Runnable object’s run method is executed.

Thread and task separation – Thread + implements the Callable interface

While Runnable is nice, there is a drawback that you can’t get the result of the task because its run method returns void.

This makes Callable a perfect choice for threads that need to obtain the results of task execution.

Callable and Runnable are basically the same:

Compared to Runnbale, Callable simply changes run to call. Of course, the most important thing is! Unlike void Run, this call method has a return value and can throw an exception.

A natural idea, then, is to pass the Callable to the Thread as a task object, and then the Thread overrides the call method.

But, unfortunately, Thread does not accept Callable arguments in the constructor.

Therefore, we need to wrap the Callable as Runnable so that we can pass it to the Thread constructor.

For this, FutureTask is the best choice.

As you can see, FutureTask indirectly inherits the Runnable interface, so it can also be thought of as a Runnable object that can be passed as a parameter to the Constructor of the Thread class.

In addition, FutureTask indirectly inherits the Future interface, which defines the method get to get the return value of call() :

Consider the following code, which defines a task object using Callable, wraps the Callable as FutureTask, and passes the FutureTask to the Thread constructor to create a Thread object.

In addition, the generic types of Callable and FutureTask fill in the type of result returned by the Callable task (that is, the return type of the Call method).

class MyCallable implements Callable<Integer> {
    @Override
    public Integer call(a) throws Exception {
        // The task to be performed.return 100; }}// Wrap Callable as FutureTask, which is also a Runnable
MyCallable callable = new MyCallable();
FutureTask<Integer> task = new FutureTask<>(callable);
// Create a thread object
Thread t3 = new Thread(task);
Copy the code

When the thread is running, we can get the result of the task using FutureTask’s get method:

Integer result = task.get();
Copy the code

Note, however, that the GET method blocks the thread that is currently calling it. For example, if we call the get method on the main thread to get the result of the t3 task, the main thread will continue to execute only if the call method returns successfully.

In other words, if the Call method never gets a result, the main thread never runs down.

Starting a thread

OK, so now that we’ve successfully created the thread, how do we get it started?

Take the first way to create a thread:

// Create a thread
Thread t1 = new Thread("t1") {
	@Override
	// The run method implements the task to be executed
	public void run(a) {
		// The task that the thread needs to perform. }};// Start the thread
t1.start();
Copy the code

Here’s a classic interview question: why start a thread instead of run?

Using the run method to start a thread doesn’t seem like a problem, right? The run method defines the task to be executed.

This is true, the task does execute correctly, but not in a multithreaded fashion. When we use T1.run (), the program is still run in the main thread that created t1, and no new T1 thread is created.

Here’s an example:

// Create a thread
Thread t1 = new Thread("t1") {
	@Override
	// The run method implements the task to be executed
	public void run(a) {
		// The task that the thread needs to perform
        System.out.println("Commence execution"); Filereader.read (file address);/ / read the file}}; t1.run(); System.out.println("Executed");
Copy the code

If a thread is started using the run method, the statement “execute completed” is printed only after the file has been read, which means that reading the file is still synchronous. Let’s say the read takes 5 seconds, and if there’s no thread scheduling, the CPU can’t do anything for 5 seconds, and everything else has to pause.

If you start a thread with the start method, the sentence “execute completed” is printed quickly before the file is read. Because multithreading makes method execution asynchronous, the file reading is done by the T1 thread and the main thread is not blocked.

| flying veal 🎉 pay close attention to the public, get updates immediately

  • I am a postgraduate student in Southeast University and a summer intern in Java background development of Ctrip. I run a public account “Flying Veal” in my spare time, which was opened on 2020/12/29. Focus on sharing computer fundamentals (data structure + algorithm + computer network + database + operating system + Linux), Java technology stack and other related original technology good articles. The purpose of this public account is to let you can quickly grasp the key knowledge, targeted. Pay attention to the public number for the first time to get the article update, we progress together on the way to growth
  • And recommend personal maintenance of open source tutorial project: CS-Wiki (Gitee recommended project, has accumulated 1.7K + STAR), committed to creating a perfect back-end knowledge system, in the road of technology to avoid detours, welcome friends to come to exchange learning ~ 😊
  • If you don’t have any outstanding projects, you can refer to the Gitee official recommended project of “Open Source Community System Echo” written by me, which has accumulated 700+ star so far. SpringBoot + MyBatis + Redis + Kafka + Elasticsearch + Spring Security +… And provide detailed development documents and supporting tutorials. Echo Echo Echo Echo Echo Echo Echo Echo Echo Echo Echo Echo Echo Echo