Summary of Java Basics (84)-Detailed Explanation of Basic Thread Methods

Original link

What is a thread

Thread is the smallest unit of operating system scheduling. There can be multiple threads in a process. These threads can have their own counters, stacks, and local variables, and can access shared memory variables. The advantage of multithreading is that it can improve response time and throughput.

Use multithreading

When a process is running, at least one thread is running.

public class Test {
    public static void main(String[] args) {
        System.out.println(Thread.CurrentThread().getName()); // 输出main
    }
}

The output of the above program is main. In fact, a thread called main is executing the main method. The output main has nothing to do with the main method.

Inherit Thread

There are two ways to implement multithreading, one is to inherit the Thread class, and the other is to implement the Ruannable interface. We can look at the structure of the Thread class

public class Thread implents Runnable

Create your own thread class MyThread and override the run method.

public class MyThread extends Thread {
    @Override
    public void run() {
        super.run();
        System.out.println("Mythread");
    }
}
public class Run() {
    public static void main(String[] args) {
        Mythread myThread = new MyThread();
        myThread.start():
        System.out.println("运行结束");
    }
}

The output above is

运行结束
MyThread

Implement the Runnable interface

If the thread class created first already has a parent class, then Thread cannot be inherited, because Java only supports single inheritance. Then pinch can implement the Runnable interface.

public class MyRunnable imiplements Runnable {
    @Override
    public void run() {
        System.out.println("运行中");
    }
}

How does it work? Let's take a look at the constructor of Thread?

Thread can be created by adding Runnable interface.

public class Run {
    public static void main(String[] args) {
        Thread thread = new Thread(runnable);
        thread.start();
        System.out.println("运行结束!");
    }
}

Instance variables and thread safety

The instance variables of the custom thread class can be shared or not shared by other threads, and distinguishing them is very important for thread safety.

The case where threads do not share data

public MyThread extends Thread {
    private int count = 5;
    public MyThread(String name) {
        super();
        this.setName(nanme);  //线程的名字
    }
    @Override
    public void run(){
        super.run();
        while(count > 0 ) {
            count--;
            System.out.println("由"+this.currentThread().getName() +" 计算. count=" + count);   
        }

   }
}

public class Run {
    public static void main(String[] args) {
        MyThread a = new MyThread("A");
        MyThread b = new MyThread("B");
        MyThread c = new MyThread("C");
        a.start();
        b.start();   
        c.start();
    }
}

How to share data?



public class MyThread extends Thread {

    private int count = 5;
    
    @Override
    public void run() {
        super.run();
        while(count > 0) {
            count--;
            System.out.println("由" + this.currentThread().getName() + "计算,count =" + count);
        }
    }
}
public class Run() {
    public static void main(String[] args) {
    MyThread mythread = new MyThread();
    Thread a = new Thread(mythread, "A");
    Thread b = new Thread(mythread, "B");
    Thread c = new Thread(mythread, "C");
    a.start();
    b.start();
    c.start();
    }

}

The above thread shares the count data in MyThread, so the above code is thread-unsafe. The easiest way to solve this problem is to achieve thread safety through synchronization.

currentThread method

There is a currentThread method in the Thread class, this method can view the information of the current thread, such as the name of the current thread.

isAlive method

It is used to judge whether the current thread is active and what is the active state. The active state means that the thread has been started and has not been terminated.

sleep() method

Method sleep method means to let the currently executing thread sleep within a specified number of milliseconds. The currently executing thread refers to the result of this.currentThread().

Stop thread

There are the following ways to terminate an ongoing thread in Java:

  • Use the exit flag to make the thread exit normally, that is, the thread terminates when the run method is completed
  • Use the stop method to forcibly terminate the thread, but it is not recommended, because stop and suspend are both expired methods
  • Use the interrupt method to interrupt the thread

Unstoppable thread

The following example calls the interrupt() method to stop the thread, but the effect of using the interrupt method is not like for+break. The interrupt method is just called 当前线程中打一个停止的标记.

public class MyThread extends Thread {
    @Override
    public void run() {
        super.run();
        for(int i = 0 ; i < 50000; i++) {
            System.out.println("i = " + (i + 1));
        }
    }
}

public class  Run {
    public static void main(String[] args) {
        try {
            MyThread my_thread = new MyThread();
            my_thread .start();
            Thread.sleep(2000);
            my_thread.interrupt();
        } catch(InterruptException e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
     }
    
}

As a result, 500,000 lines of logs are still printed, so calling the interrupt method does not stop the thread.

Determine whether the thread is stopped

In the Thread class, there are two methods:

  • this.interrupted(), test whether the current thread has been interrupted
  • this.isInterrupted(), test whether the thread has been interrupted

Let's take a look at this.interrupted()the explanation of the method: test whether the current thread has been interrupted, the current thread refers to the thread that executes this method call.

public class MyThread extends Thread {
    @Override
    public void run() {
        super.run();
        for(int i = 0; i < 50000; i++) {
            System.out.println("i = " + ( i + 1));
        }
    }
}
public class Run {
    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread();
            thread.start();
            thread.interrupt();
            System.out.println("是否停止1 ? ="+ thread.interrupted());
            System.out.println("是否停止2 ? =" + thread.interrupted());
        } catch(InterruptedException e) {
            System.out.prinln("main catch");
            e.printStackTrace();
        }
        System.out.println("end");
    }
}

We use thread.interrupted() to test whether the current thread has been interrupted, and here the current thread is the main thread, and it has never been interrupted. So the printed result is 两个false.

Take a look at the following code:

public class Run2 {
    public static void main(String[] args) {
        Thread.currentThread().interrupt();
        System.out.println("是否停止1 ?  " + Thread.interrrupted()); // true
        System.out.println("是否停止2 ?  " + Thread.interrrupted()); // false
        System.out.println("end");
    }
}

The interrupted() method does determine whether the current thread is stopped, but why the second one is false? Take a look at the manual description of the interrupted method:

Test whether the current thread has been interrupted. The thread interruption status is cleared by this method. In other words, if you call this method twice in a row, the second call will return false (after the first call has cleared its interruption status, and the second call has finished checking the interruption, the current thread is interrupted again except).

Tests whether the current thread has been interrupted. The interrupted status of the thread is cleared by this method. In other words, if this method were to be called twice in succession, the second call would return false (unless the current thread were interrupted again, after the first call had cleared its interrupted status and before the second call had examined it)

That is, the interrupted() method has a method to clear the state, so the value returned by the interrupted() method for the second call is false.

Let's take a look at the interrupted() method and then look at the isInterrupted() method, which is declared as follows:

public boolean isInterrupted();

It can be seen from the declaration that the isInterrupted() method is not static.

public class Run3 {
    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep(1000);
            thread.interrupt();
            System.out.println("是否停止1 ?==" + thread.isInterrupted()); // true
            System.out.println("是否停止2? ==" + thread.isInterrupted()); // true
        } catch(InterruptedException e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
        System.out.println("end")
    }

}

We can see that this.isInterrrupted() did not clear the status flag, so it prints two true.

Let's summarize the explanation of the two methods:

  • this.interrupted(): Test whether the current thread is already in an interrupted state. After execution, it has the function of clearing the state flag to false.
  • this.isInterrupted(): Test whether the thread Thread object is already interrupted, but does not clear the status flag.

Thread that can be stopped-exception method

public calss MyThread extends Thread {
    @Override
    public void run() {
        super.run();    
        for(int i = 0; i < 50000; i++) {
            if(this.interrupted()) {
                System.out.println("已经是停止状态!我要退出!");
                break;
            }
            System.out.println("i=" + (i + 1));
        }
    }
}
public class Run {
    public static void main(String[] args) {
        try {
            MyThread thread =new MyThread();
            thread.start();
            Thread.sleep(2000);
            thread.interrupt();
        } catch(InterruptedException e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
    }
}

Although the above example stops the thread, if there are statements below the for statement, it will continue to run.


public calss MyThread extends Thread {
    @Override
    public void run() {
        super.run();    
        for(int i = 0; i < 50000; i++) {
            if(this.interrupted()) {
                System.out.println("已经是停止状态!我要退出!");
                break;
            }
            System.out.println("i=" + (i + 1));
        }
        System.out.println("我被输出,如果此代码是for又继续运行,线程并未停止!");
    }
}


public class Run {
    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread() ;
            thread.start();
            Thread.sleep(2000);
            thread.interrupt();
        } catch(InterruptedException  e) {
            System.out.println("main catch");
           e.printStackTrace();
        }
        
    }
}

The above code can be 我被输出,如果此代码是for又继续运行,线程并未停止!output. Explain that if you stop the thread in time and jump out of the for loop, the statement following the for will also be executed. This shows what the problem is: thread.interrupt is just a flag to indicate that the thread is to be stopped, while this.interrupted() can only detect this flag and clear the flag service.

So how do you say that the thread stops?

public calss MyThread extends Thread {
    @Override
    public void run() {
        try {
            super.run();    
            for(int i = 0; i < 50000; i++) {
                if(this.interrupted()) {
                    System.out.println("已经是停止状态!我要退出!");
                    throw new InterruptedException();
                    break;
                }
                System.out.println("i=" + (i + 1));
            }
            System.out.println("我被输出,如果此代码是for又继续运行,线程并未停止!");
        } catch (InterrruptedException e) {
            System.out.println("进MyThread.java类run方法中的catch了");
        }
    }
}


public class Run {
    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread() ;
            thread.start();
            Thread.sleep(2000);
            thread.interrupt();
        } catch(InterruptedException  e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
        
    }
}

Stop in sleep

What is the effect if the thread is in sleep state?

public calss MyThread extends Thread {
    @Override
    public void run() {
        try {
            super.run();    
            System.out.println("run begin")
            Thread.sleep(20000); //睡觉20s
            System.out.println("run end");
        } catch (InterrruptedException e) {
            System.out.println("在睡觉中被停止,进入catch!" + this.isInterrupted()); // 结果打印false。
        }
    }
}
public class Run {
    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread() ;
            thread.start();
            Thread.sleep(2000);
            thread.interrupt();
        } catch(InterruptedException  e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
        
    }
}

From the result point of view, if a thread is stopped in the sleep state, then the catch statement will be entered, and the stop state value will be clear, making it false.

Pause thread

Suspending a thread means that the thread can resume execution. In java multithreading, you can use the suspend() method to suspend the thread and the resume() method to resume the execution of the thread.

public class MyThread extends Thread {
    private long i = 0;
    public long getI()  {
        return i;
    }
    public void setI(int i) {
        this.i = i;
    }
    @Override
    public void run() {
        while(true) {
            i++;
        }
    }
}

public class Run {
    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep(5000);
            thread.suspend();
            System.out.println("A=" + System.currentTimeIillis() + " i =" + thread.getI());
            Thread.sleep(5000);
            System.out.println("A=" + System.currentTimeMIillis() + " i =" + thread.getI());
            
            // B段
            thread.resume();
            Thread.sleep(5000);
            // C段
            thread.suspend();
            System.out.println("B= " + System.currentTimeMillis()  + " i = " + thread.getI());
            Thread.sleep(5000);
            System.out.println("B = " + System.currentTimeMillis()  + " i = " + thread.getI() );
        
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
    }

}

Disadvantages of suspend and resume methods-exclusive

If a thread acquires the lock of a certain resource, but it suspends, then subsequent threads cannot acquire the lock.

yield method

This method is used to give up the current CPU resources and give it to other tasks to occupy the CPU execution time. But the time to give up is uncertain. It is possible that you have just given up and get a time slice immediately.

A hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore this hint.

Guess you like

Origin blog.csdn.net/lsx2017/article/details/113922027