Thread Foundation

Keywords: Java JDK jvm

Thread Foundation

1. Understanding threads in java

1) Programs in java are inherently multithreaded

public static void main(String[] args) {
    ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
    ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
    for (ThreadInfo threadInfo : threadInfos) {
        System.out.println("["+threadInfo.getThreadId()+"]"+" "+threadInfo.getThreadName());
    }
}

/**
 * [6] Monitor Ctrl-Break
 * [5] Attach Listener
 * [4] Signal Dispatcher
 * [3] Finalizer
 * [2] Reference Handler
 * [1] main
 */

As you can see, we just started a main method, and the java virtual machine also started six threads for us, so we say that programs in java are inherently multi-threaded.

2. Three ways to start multithreading in java

Learn from: https://blog.csdn.net/m0_38075425/article/details/81606156

1. Inheriting the Thread class

Create and start multithreading by inheriting the Thread class as follows:

1. Define a subclass of the Thread class and override the run() method of that class. The body of the run() method represents the task that the thread needs to complete. So the run method is called thread executor.

2. Create an instance of Thread subclass, that is, create thread objects.

3. Call the start() method of the thread object to start the thread.

private static class testThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10 ; i++) {
            System.out.println(Thread.currentThread().getName()+" Implemented "+i);
        }
    }

}
//test
public static void main(String[] args) {
    new testThread().start();
    for (int i = 0; i < 10 ; i++) {
        System.out.println(Thread.currentThread().getName()+" Implemented "+i);
    }
}

/**results of enforcement
main Implemented 0
Thread-0 Implemented 0
main Implemented 1
main Implemented 2
main Implemented 3
Thread-0 Implemented 1
main Implemented 4
Thread-0 Implemented 2
main Implemented 5
Thread-0 Implemented 3
main Implemented 6
Thread-0 Implemented 4
main Implemented 7
Thread-0 Implemented 5
Thread-0 Implemented 6
main Implemented 8
*/

You can see that the for loop of the main thread and thread0 thread executes alternately, and the thread starts successfully. In this instance program, Thread1 inherits the Thread class and rewrites the run method. In the run method, we print out the name of the thread currently executing which thread is executing, how many times it is executing, and use member variable i to record the number of executions. In main function, we create the instance object of this thread, and start this thread through start method. When we execute, we can see that the thread runs in a preemptive way. Although only one thread instance is created, there are actually two threads running, and there are thread executions of the main thread represented by the main method.

  In addition, we have learned two ways of threading:

  1.Thread.currentThread(), which is a static method of the Thread class, always returns the thread object currently being executed.

  2.getName(): This method is an instance method of the Thread class, which returns the name of the thread currently executing. By default, the name of the main thread is main, and the name of the user-initiated multithreads is Thread-0,Thread-1,Thread-3..Thread-n, etc.

2. Implementing Runnable Interface

The steps to implement the Runnable interface creation and start multithreading are as follows:

1. Define the implementation class of the Runnable interface and override the run method of the interface. The run method body is also the thread executor of the thread.

2. Create an instance object of the Runnable implementation class, and use the instance object as the target of Thread to create the Thread class. The Thread object is the real thread object.

3. Call the start() method of the thread object to start the thread.

private static class testRunnable implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 10 ; i++) {
            System.out.println(Thread.currentThread().getName()+" Implemented "+i);
        }
    }
}
//test
public static void main(String[] args) {
    new Thread(new testRunnable()).start();
    for (int i = 0; i < 10 ; i++) {
        System.out.println(Thread.currentThread().getName()+" Implemented "+i);
    }
}

In particular, note that the name in the main function does not directly execute the run method of Thread2, but instead fills Thread2 into Thread and starts with the start method. The Runnable implementation class contains run methods only as thread executors, while the actual thread object is still the Thread instance object, and Thread is the object that actually creates threads.

3. Implementing interface Callable<>

The steps to implement Callable interface creation and start multithreading are as follows:

1. Define the implementation class of the Callable interface and rewrite the call method of the interface. Callable can interface with a generic type as a return value type.

2. Create an instance object of Callable implementation class, because the Thread class can not directly receive a Callable class as a parameter. So we also need to create the FutureTask instance object to accept the instance object of the Callable implementation class, and then we use this instance object as the target of Thread to create the Thread class.

3. Call the start() method of the thread object to start the thread, and we can get the return value of the call method through the get() method of the FutureTask object.

private static class testCallable implements Callable<String>{
    @Override
    public String call() throws Exception {
        System.out.println("I am implements Callable");
        return "CallResult";
    }
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
    FutureTask<String> futureTask = new FutureTask<>(new testCallable());
    new Thread(futureTask).start();
    System.out.println(futureTask.get());
}

/** results of enforcement
I am implements Callable
CallResult
*/

3. How to make the thread in java stop working safely

In the original version of JDK, the Thread class provided a thread termination method called stop(), but now it is found in the JDK source code that the stop() method has been discarded. The main reason is that the stop() method is too violent. Force the termination of an executing thread. This will cause some data inconsistencies.

public void Thread.interrupt()        //Interrupt thread
public boolean Thread.isInterrupted() //Determine whether the thread is interrupted
public static boolean Thread.interrupted() //Determine whether an interrupt has occurred and clear the current interrupt status

The Thread.interrupt() method is an instance method that notifies the target thread of interruption and sets the interrupt flag bit. The interrupt flag indicates that the current thread has been interrupted.

The Thread.isInterrupted() method is also an instance method, which checks whether the current thread has been interrupted (by checking the interrupt flag bit), and the return value is boolean type.

The Thread.interrupted() method is also used to determine whether the current thread has been interrupted, while clearing the interrupt flag status of the current thread.

Test program

public static void main(String[] args) throws ExecutionException, InterruptedException {
    Thread thread = new Thread(){
        @Override
        public void run() {
            //Interrupt Processing Logic
            while (true){
                System.out.println("The thread is waiting for interrupted!");
                /*if (Thread.currentThread().isInterrupted()){
                        System.out.println("The thread is interrupted!");
                        break;
                    }*/
            }
        }
    };
    thread.start();
    thread.interrupt();//Interrupt thread
}

/**
The thread is waiting for interrupted!
The thread is waiting for interrupted!
The thread is waiting for interrupted!
The thread is waiting for interrupted!
The thread is waiting for interrupted!
The thread is waiting for interrupted!
.....
*/

You can see that if interrupt() is used separately to interrupt a thread, the thread is not actually interrupted.

public static void main(String[] args) throws ExecutionException, InterruptedException {
    Thread thread = new Thread(){
        @Override
        public void run() {

            while (true){
                System.out.println("The thread is waiting for interrupted!");
                if (Thread.currentThread().isInterrupted()){
                    System.out.println("The thread is interrupted!");
                    break;
                }
            }
        }
    };
    thread.start();
    thread.interrupt();//Interrupt thread
}

/** results of enforcement
The thread is waiting for interrupted!
The thread is interrupted!
*/

Note: When thread A calls thread B's interrupt method, if thread B is blocking (such as sleep, wait, etc.), then InterruptExcpetion will be thrown, and the interrupt state of thread B will be reset false. At this time, two methods are used:

First, when InterruptException is captured, the interrupt state of the thread can be reset to true in catch and logged. Doing so is equivalent to maintaining the interrupt state of thread B unchanged.

2. Continue to throw the exception.

public static void main(String[] args) throws ExecutionException, InterruptedException {
    Thread thread = new Thread(){
        @Override
        public void run() {

            while (true){
                try {
                    sleep(2000);
                } catch (InterruptedException e) {
                    interrupt();
                    e.printStackTrace();
                }
                if (Thread.currentThread().isInterrupted()){
                    System.out.println("The thread is interrupted!");
                    break;
                }
            }
        }
    };
    thread.start();
    thread.interrupt();//Interrupt thread
}

IV. Thread Life Cycle

1. Life Cycle Map

The following is a lifecycle diagram of a thread:

2.start() and run() methods

1.start() method is used to start threads, which really implements multithreading. Instead of waiting for the run method body code to be executed, you can continue to execute the following code directly; you can start a thread by calling the start() method of the Thread class, when the thread is ready and not running. This Thread class then calls the method run() to complete its operation. Here the method run() is called thread body. It contains the content of the thread to be executed. The Run method runs out and the thread terminates. The CPU then schedules other threads.
2. The run() method is called as a normal method. If the first thread object does not call the start() method and directly calls the run() method, the JVM does not add this thread to the thread stack, but the main thread calls the run() method.

Posted by dave_c00 on Sun, 13 Oct 2019 01:41:50 -0700