Thread and Runnable

1. Two ways to create a thread

How do you create threads in Java? You’ll soon be able to think of two ways to inherit Thread and implement the Runnable interface.

Yes, Java provides both ways to create new threads.

There are various articles on the web that explain the differences between the two methods of thread creation, but what we’re going to talk about here is the connection between the two methods.

Let’s take a look at the code for both methods:

1, inherit Thread class, overwrite run method

Public class MyThread extends Thread {@override public void run() {system.out.println (); } public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); }}Copy the code

2. Implement Runnable interface and run method

Public implements Runnable {@override public void run() {system.out.println (" implements Runnable "); } public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); new Thread(myRunnable).start(); }}Copy the code

In the first approach, Thread subclasses override the run method of their parent class to create threads.

In the second case, the object of the class implementing the Runnable interface can be passed as a parameter to the created Thread object. So what is Runnable? What are the secrets of the Thread class?

2. Association between Thread and Runnable

Let’s look at Runnable source code:

public interface Runnable {    
  public abstract void run();
}
Copy the code

What? Runnable interface as simple as that? Just one run method?

Yes, you read that right, the Runnable interface is as simple as that. Without the Thread class, the Runnable interface is as common as it gets, and we can’t implement it in code without doing anything! But thanks to the Thread class’s favor, this interface is different!

So where does the Runnable interface get the Thread class’s favor? Let’s start by looking at the definition of the Thread class

public class Thread implements Runnable{}
Copy the code

Thread is an implementation of Runnable. To the programmer’s first instinct, the Thread should naturally implement the run method, we continue to search in the source code!

@Override
public void run() {        
  if (target != null) {
        target.run();
  }
}
Copy the code

Sure enough, Thread implements the run method and has the judgment that if target is null, it does nothing, otherwise it executes target’s run method. What is Target?

private Runnable target;
Copy the code

Target is also a Runnable object, so where is the private field assigned? We continue to find that the assignment is done in the init method, and we end up calling the init method in the constructor. Let’s look at the constructor definition.

public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}
Copy the code

Thread_runnable (thread_runnable); thread_runnable (thread_runnable);

1, Runnable originally civilian, just a common interface. Thread implements the Runnable interface and the run method of the interface. Thread provides an overloaded constructor that accepts arguments of type Runnable. Thread overrides the run method of the Runnable implementation class that calls the constructor passed in.

So no matter how we create a thread, we implement or override the run method! And the run methods are all implemented in the Runnable interface. The run method is our custom logic that needs to be handled in the thread! So where is this run method called? Can a new thread be created by calling the run method directly? Why do we call the start method in our code to start a thread? How does the start method relate to the run method?

Driven by curiosity, I opened the start method in the source code again and found that the most important behavior in this method is to call a method named start0.

Public synchronized void start() {...... start0(); ... }Copy the code

So what’s start0?

private native void start0();
Copy the code

See native keyword we should know, this method is JVM method, specific implementation need to see C code!

3, start method and run method association

In view of my C language is very bad, and not touched for many years, but want to find out the connection between the start method and the run method, so on the Internet to find the relevant information, the following do some sorting.

The difference between multi-threaded start and run methods.

References:

www.ibm.com/developerwo…

In the top of the Thread class, there is a native registerNatives method. The main function of this method is to register some local methods for the Thread class to use, such as start0(), stop0(), etc., so to speak, It registers all local methods that operate on local threads. This method is placed in a static statement block, which indicates that when the class is loaded into the JVM, it will be called to register the corresponding local method.

private static native void registerNatives(); static { registerNatives(); }}Copy the code

The local method registerNatives is defined in the thread. c file. T

Hread. c is a small file that defines common data and operations on threads used by various operating system platforms

JNIEXPORT void JNICALL Java_Java_lang_Thread_registerNatives (JNIEnv *env, jclass cls){ (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods)); } static JNINativeMethod methods[] = {...... {" start0 ", "V" (), (void *) & JVM_StartThread}, {" stop0 ", "V" (" OBJ "), (void *) & JVM_StopThread},... };Copy the code

It is easy to see how the Java thread calling the start method actually calls the JVM_StartThread method. In fact, what we need (or Java presentation behavior) is for this method to eventually call the Run method of the Java thread, which it does. In jvm.cpp, there is the following code snippet:

JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jThread))...... native_thread = new JavaThread(&thread_entry, sz); ...Copy the code

Here JVM_ENTRY is a macro that defines the JVM_StartThread function, and you can see that the actual platform-specific local thread is created within the function. The thread function is thread_entry, as shown below.

static void thread_entry(JavaThread* thread, TRAPS) {
  HandleMark hm(THREAD);
   Handle obj(THREAD, thread->threadObj());
   JavaValue result(T_VOID);
   JavaCalls::call_virtual(&result,obj,
   KlassHandle(THREAD,SystemDictionary::Thread_klass()),
   vmSymbolHandles::run_method_name(),
   vmSymbolHandles::void_method_signature(),THREAD);
}
Copy the code

You can see that the vmSymbolHandles::run_method_name method was called, which is defined in the vmSymbols.hpp macro:

Class vmSymbolHandles: AllStatic {... The template (run_method_name, "run")... }Copy the code

How run_method_name is declared is not covered in this article because it involves tedious code details. Interested readers can check out the JVM source code for themselves.

To sum up, the Java thread creation call is as shown above. First, the Java thread’s start method creates a local thread (by calling JVM_StartThread) whose thread function is thread_entry defined in jVM.cpp. It further calls the run method.

You can see that there is no essential difference between a Java thread’s run method and a normal method. A direct call to the run method does not generate an error, but it is executed in the current thread rather than creating a new thread. A series of concurrent interview questions and answers, I have all sorted out.

FutureTask, Callable and Runnable

1. Create an asynchronous thread that can fetch results

We understand the create a thread to create the above two ways, but we can also see that created by runnable threads unable to get the return value, if we need to asynchronous perform an operation, and get the result returned, may be the above two ways of creating threads will be not apply (also is not to say that can not be, for instance through Shared variables, But it will be more troublesome to use)! A convenient way to do this in Java is to use the FutureTask class.

public class MyFutrueTask implements Callable<String> { @Override public String call() throws Exception { System.out.println(" I am a thread in Future mode "); Return "Future mode thread terminated "; } public static void main(String[] args) throws TimeoutException, ExecutionException, InterruptedException { FutureTask<String> futureTask = new FutureTask<String>(new MyFutrueTask()); new Thread(futureTask).start(); String result = futureTask.get(2000, TimeUnit.MILLISECONDS); System.out.println(result); }}Copy the code

The main class implements an interface called Callable, and implements the call method of the interface. The specific business logic is implemented in the call method! The object of the class implementing the Callable interface can be passed as a parameter to the constructor of the created FutureTask object, which in turn is passed as a parameter to the constructor of the Thread object…

If Thread is passed as a parameter to the Thread constructor, it must implement the Runnable interface. Does that mean that FutureTask should be a Runnable implementation class?

2. FutureTask implementation

Let’s first look at the definition of the FutureTask class

public class FutureTask<V> implements RunnableFuture<V>
Copy the code

FutureTask is a generic class and implements the RunnableFutrue generic interface, so we’ll follow up

public interface RunnableFuture<V> extends Runnable, Future<V> {   
    void run();
}
Copy the code

The RunnableFutrue interface inherits the Runnable interface, which means that FutureTask indirectly implements the Runnable interface. FutureTask is also an implementation of Runnable, so it must implement the Run method. You can also pass instance objects into the Thread object’s post-construct function! The RunnableFutrue interface also inherits another generic interface called Futrue. Let’s look at the definition of this interface

public interface Future<V> {
   boolean cancel(boolean mayInterruptIfRunning);
   boolean isCancelled();
   boolean isDone();
   V get();
   V get(long timeout, TimeUnit unit);
}
Copy the code

As you can see from the names of these methods, once FutureTask implements the Future interface, it should have the ability to cancel threads, determine thread status, retrieve results, and so on!

Let’s look at the FutureTask class diagram as a whole:

What about the implementation of these interfaces in the FutureTask class? We can explore this in the FutureTask class, starting with the constructor

public interface Future<V> {
   boolean cancel(boolean mayInterruptIfRunning);
   boolean isCancelled();
   boolean isDone();
   V get();
   V get(long timeout, TimeUnit unit);
}
Copy the code

The constructor takes a parameter of type Callable, which is a generic-type interface that has only one method named Call. Originally, this was just a normal interface, but because FutrueTask “favored”, this interface has become unusual!

public interface Callable<V> {    
  V call() throws Exception;
}
Copy the code

Does it look like a Runnable interface at first glance? But the Call method of the Callable interface returns a value! How do Callable, Runnable, and FutureTask relate to each other? FutureTask implements a Runnable class. Should FutureTask also implement the Run method? Let’s follow the code:

public void run() {
    ......
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                ......
            }
            if (ran)
                set(result);
        }
    } finally {
        ......
    }
}
Copy the code

The implementation of the Run method is also relatively simple; the code above only preserves the code that needs attention.

In the run method, the Callable passed in by the constructor is called to implement the call method of the class, and the result variable is used to receive the return value of the method. Finally, the set method is called to set the return result to the class property. Since FutureTask implements the Future interface, So you have the ability to get the return value and determine if the thread is finished or canceled!

That is, the call method of our custom Callable implementation class will eventually be executed in the Run method of FutureTask (aka Runnable)! The run method in Runnable, in turn, is executed in the Run method of Thread.