Java thread API, article summary

Keywords: Java Back-end Multithreading

Thread creation

Inherit Thread class

You can create a Thread by inheriting the Thread class and creating an object through new.

	public class MyThread extends Thread {
	    private int count = 5;
	
	    @Override
	    synchronized public void run() {
	        super.run();
	        count--;
	        System.out.println("from " + this.currentThread().getName() + " calculation, count=" +count);
	    }
	}
    // Start thread
	public class Run {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        Thread a = new Thread(myThread, "A");
        a.start();
    }
}

Implement Runnable interface

You can create a Thread by implementing the Runnable interface and passing it to the Thread's construction method in the form of construction parameters.

	public class MyRunnable implements Runnable {
	    @Override
	    public void run() {
	        System.out.println("In operation");
	    }
	}
	// Start thread
	public class Run {
	    public static void main(String[] args) {
	        Thread thread = new Thread(new MyRunnable());
	        thread.start();
	        System.out.println("End of operation");
	    }
	}

Comparison of the differences between the two methods

Firstly, Thread implements the Runnable interface, so theoretically, the construction method of Thread can pass both the Thread object and the Runnable implementation class.
Secondly, the internal processes of the two methods are different:

  1. Method of inheriting Thread: create a Thread directly by creating an object, and directly call the run() method.
  2. The Runnable interface is implemented: calling the run method of Thread, calling init() method, assigning the target, then calling run() method, making the sentence empty, not empty, executing target run method, and executing the run method of the target.
    Finally, due to the single inheritance of java, there are many limitations, which can be extended by implementing the Runnable interface.

Dealing with thread concurrency security

Synchronization code blocks, synchronization methods, and locks are detailed in the following articles.

Java thread API

currentThread()

This method returns which thread the current code is called by.
At the beginning, I didn't understand multithreading, nor did I understand the return value of this method. Why are different threads called in the same object.
Because the construction method is created by the main function, and the run method is called by a new thread, the return value is different.

	public class MyThread extends Thread{
	    public MyThread() {
	        System.out.println("Construction method printing:"+Thread.currentThread().getName());
	    }
	
	    @Override
	    public void run() {
	        System.out.println("run Print:" + Thread.currentThread().getName());
	    }
	}

	public class Run2 {
	    public static void main(String[] args) {
	        MyThread myThread = new MyThread();
	        myThread.run();
	        myThread.start();
	    }
	}

start() and run()

The start method creates a thread and automatically calls the run method; The run method is called to execute immediately without starting a new thread.

isAlive()

The function of this method is to judge whether the current thread is alive.

	public class MyThread extends Thread {
	    @Override
	    public void run() {
	        System.out.println("run=" + this.isAlive());
	    }
	}
	
	public class Run {
	    public static void main(String[] args) {
	        MyThread myThread = new MyThread();
	        System.out.println("begin == " + myThread.isAlive());
	        myThread.start();
	        try {
	            Thread.sleep(5);
	        } catch (InterruptedException e) {
	            e.printStackTrace();
	        }
	        System.out.println("end == " + myThread.isAlive());
	    }
	}

sleep()

This method pauses the thread execution, enters the Blocked state, and gives up the cpu fragment to other threads.

	public class MyThread2 extends Thread {
	    @Override
	    public void run() {
	        try {
	            System.out.println("run threadName="+this.currentThread().getName()+" begin =" + System.currentTimeMillis());
	            Thread.sleep(2000);
	            System.out.println("run threadName=" + this.currentThread().getName()+" end =" + System.currentTimeMillis());
	        }catch (Exception e){
	            System.out.println(e.getMessage());
	        }
	    }
	}
	
	public class Run1 {
	    public static void main(String[] args) {
	        MyThread2 myThead = new MyThread2();
	        System.out.println("begin =" + System.currentTimeMillis());
	        myThead.start();
	        System.out.println("end =" + System.currentTimeMillis());
	    }
	}

yield()

The function of this method is to give up the current CPU resources, but will not give up the synchronization lock, and it is impossible to determine the event of the next application for CPU resources.

Thread stop

There are three methods in Java to terminate a running thread:

  • Use the exit flag to make the thread exit normally.
  • Using the stop method to forcibly terminate a thread is not recommended.
  • Interrupt the thread using the interrupt method.

Interrupt a thread using the interrupt method

The interrupt method can be called, which is equivalent to setting an interrupt flag for the Thread, and the Thread can still execute. At this time, we can judge the status through the interrupted() method or isInterrupted() method, so as to stop the Thread.

The difference between interrupted() and isInterrupted()

  • The interrupted method is modified by static. It is generally called through Thread.interrupted, but its source code essence is currentThread.isInterrupted(true) called through interrupted().
  • After the interrupted() method tests whether the current thread is in an interrupted state, it returns the state and deletes the state, resulting in inconsistent return values when the method is called twice. isInterrupted() does not delete the interrupt state.
	public class MyThread extends Thread {
	    @Override
	    public void run() {
	        super.run();
	        for (int i = 0; i < 80000; i++) {
	            if (Thread.interrupted()){
	                System.out.println("It's already stopped. Exit!");
	                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(100);
	//            thread.interrupt();
	//            Thread.currentThread().interrupt();
	            System.out.println("Stop 1?=" + thread.interrupted());
	            System.out.println("Stop 2?=" + thread.interrupted());
	        }catch (Exception e){
	            e.printStackTrace();
	        }
	        System.out.println("end!");
	    }
	}
	
	
	public class Run3 {
	    public static void main(String[] args) {
	        try {
	            MyThread thread = new MyThread();
	            thread.start();
	//            Thread.sleep(5000);
	            thread.interrupt();
	            System.out.println("Stop 1?=" + thread.isInterrupted());
	            System.out.println("Stop 2?=" + thread.isInterrupted());
	        }catch (Exception e){
	            e.printStackTrace();
	        }
	        System.out.println("end!");
	    }
	}

Anomaly method

Although thread interrupts can be marked through the interrupt() method, and the interrupt status of the thread can be judged in combination with Thread.interrupted(), if there is code in addition to the judgment statement, it will still be executed.

public class MyThread extends Thread {
    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 500000; i++) {
            if (Thread.interrupted()){
                System.out.println("stop it! sign out!");
                break;
            }
            System.out.println("i=" + (i+1) );
        }
        System.out.println("I am output if this code is for Execution continued without the thread stopping");
    }
}

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

You can see that although the loop statement ends, the final South is still output, which means that the thread has not completely stopped. In order to solve this problem, the thread stop can be controlled in an abnormal way.

public class MyThread extends Thread {
    @Override
    public void run() {
        super.run();
        try {
            for (int i = 0; i < 500000; i++) {
                if (Thread.interrupted()){
                    System.out.println("It's already stopped! sign out!");
                    throw new InterruptedException();
                }
                System.out.println("i=" + (i+1));
            }
            System.out.println("Is it still implemented?");
        }catch (InterruptedException e){
            System.out.println("enter MyThread.java class run Methodical catch It's over!");
            e.printStackTrace();
        }
    }
}

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

It is worth noting that sleep() and interrupt() cannot be used together. Exceptions will occur whether sleep() or interrupt() is executed first.

stop() stops the thread

The stop() method can forcibly terminate the thread, but it is obsolete because of its serious side effects.
stop() may have the following consequences:

  • The final cleanup cannot be completed and resources cannot be released.
  • Because stop() will also release the lock after stopping the thread, it is easy to cause data inconsistency.

return termination method

Since the coding of this method is not very elegant, it will not be shown. It is also combined with the interrupt method, but replace the exception with reuturn; However, due to exceptions, fianlly can be used for some universal resource operations, which is much more elegant.

Pause thread

Suspend () is combined with resume() method. The former is thread pause and the latter is thread resume.
Because the use of these two methods will cause some problems, they are also abandoned.
So what's the problem?

  • resource hog
  • Incomplete data

resource hog

If a thread preempts a thread safe resource and is called by suspend (), the resource will be preempted forever and cannot be unlocked, which may cause deadlock.

public class SynchronizedObject {
    synchronized public void printString() {
        System.out.println("begin");
        if (Thread.currentThread().getName().equals("a")){
            System.out.println("a Threads are forever suspend Yes");
            Thread.currentThread().suspend();
        }
        System.out.println("end!");
    }
}

public class Run {
    public static void main(String[] args) {
        try {
            final SynchronizedObject obj = new SynchronizedObject();

            Thread thread = new Thread() {
                @Override
                public void run() {
                    obj.printString();
                }
            };
            thread.setName("a");
            thread.start();

            Thread.sleep(1000);

            Thread thread1 = new Thread(){
                @Override
                public void run() {
                    System.out.println("thread1 Started, but unable to enter printString()method! Print only one begin");
                    System.out.println("because printString()Method by a The thread is locked and locked forever suspend Suspended");
                    obj.printString();
                }
            };
            thread1.start();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

Incomplete data

It is likely that the data is incomplete due to errors when other threads fetch data after the thread is suspended.

public class MyObject {
    private String username = "1";
    private String password = "11";

    public void setValue(String u, String p){
        this.username = u;
        if (Thread.currentThread().getName().equals("a")){
            System.out.println("suspend a Thread!");
            Thread.currentThread().suspend();
        }
        this.password = p;
    }

    public void printUsernamePwd(){
        System.out.println(username + " " + password);
    }
}

public class Run {
    public static void main(String[] args) {
        try{
            MyObject myObject = new MyObject();
            Thread thread = new Thread(){
                @Override
                public void run() {
                    myObject.setValue("a", "aa");
                }
            };
            thread.setName("a");
            thread.start();

            Thread.sleep(500);

            Thread thread1 = new Thread(){
                @Override
                public void run() {
                    myObject.printUsernamePwd();
                }
            };
            thread1.start();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

Posted by stevel on Sun, 31 Oct 2021 02:38:49 -0700