Common methods in Java multithreading

Posted by jigsawsoul on Sat, 25 Dec 2021 08:05:03 +0100

run() method (just an internal method)

The run() method is just an ordinary method in a class. Calling the run method is the same as calling an ordinary method.
The method run() is called the thread body. It contains the contents of the thread to be executed. The thread enters the [running state] and starts running the code in the run function.
The Run method ends and this thread terminates. An error is reported when calling the start method again.
The CPU then schedules other threads.

Start thread start() method (start a thread)

In Java, the start method is used to start multithreading.
In the start method, the real implementation of multithreading is a local method start0.
Call the start method to start a thread, and the state is ready.
Instead of waiting for the run method body code to execute, you can continue to execute the following code.

public  class TestDemo {
    public static void main(String[] args) {

        Runnable test = new  Runnable() {
            public void run() {
                String name = Thread.currentThread().getName();
                System.out.println("Currently running thread: " + name);
            }
        };

        test.run();

        // Start multithreading and execute the run method
        new Thread(test).start();
    }
}

Wait for a thread - join()

The join() method is a method in the Thread class. The definition of this method is to wait for the Thread to terminate. In fact, the join() method will suspend the execution of the calling Thread until the called object completes its execution.

Now there are two threads t1 and t2, so how to finish t1 execution and then execute t2? Here we can use the join() method,
Wait for t1 to finish executing, and then execute t2 thread!!

public  class TestDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 3; i++) {
                    try {
                        System.out.println(this.getName()+"Still running!");
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(this.getName()+"It's over!");
            }
        };
        Thread t2 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 3; i++) {
                    try {
                        t1.join();
                        System.out.println(this.getName()+"Still running!");
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(this.getName()+"It's over!");
            }
        };
        t1.start();
        t2.start();
    }
}


If we don't wait for the t1 thread to end, which of the t1 and t2 threads will execute first depends entirely on the scheduling of the operating system. That is, concurrent execution.

public  class TestDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 3; i++) {
                    try {
                        System.out.println(this.getName()+"Still running!");
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(this.getName()+"It's over!");
            }
        };
        Thread t2 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 3; i++) {
                    try {
                        //t1.join();
                        System.out.println(this.getName()+"Still running!");
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(this.getName()+"It's over!");
            }
        };
        t1.start();
        t2.start();
    }
}


At the same time, you can also set the waiting time in join(). After this time, you won't wait.

public  class TestDemo {
    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(){
            @Override
            public void run() {
                for(int i = 0 ; i < 10 ; i++){
                    System.out.println(this.getName()+"Running");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        Thread t2 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {

                    System.out.println(this.getName()+"Running");
                    try {

                        Thread.sleep(1000);

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        t1.start();
        t1.join(7000);
        System.out.println("I won't wait");
        t2.start();
    }
}

Interrupt a thread and call the interrupt() method to notify

Interrupt the t1 thread 1m after it runs.
Thread. currentThread(). A built-in flag bit of isinterrupted() does not require the user to create code judgment.
When calling the interrupt method to interrupt, two situations will be encountered.
a) Case 1: if the logic executed inside the thread does not involve waiting such as sleep, it will exit through this flag bit.

public  class TestDemo {
    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(){
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()){
                    System.out.println(Thread.currentThread().getName()+" Running");
                }
            }
        };

        t1.start();
        Thread.sleep(1000);
        t1.interrupt();
    }
}


b) Case 2: if the logic executed inside the current thread has entered the sleep, an InterruptedException will be triggered. The exception will be caught through catch, and the processing will continue to be decided.
If there is no processing here, the thread will continue to loop.

public  class TestDemo {
    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(){
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" Running");
                }
            }
        };

        t1.start();
        Thread.sleep(5000);
        t1.interrupt();
    }
}


At this time, the break here essentially allows the thread's method to end execution~
However, whether the thread ends or not depends on the method of the thread itself~

public  class TestDemo {
    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(){
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    	//e.printStackTrace(); Print exception information by yourself
                        break;
                    }
                    System.out.println(Thread.currentThread().getName()+" Running");
                }
            }
        };

        t1.start();
        Thread.sleep(5000);
        t1.interrupt();
    }
}

The currentThread() method gets the reference of the current thread object

Invoking in that thread gets the reference to that thread object.
If a Thread is created by creating a Thread subclass and overriding the run method, this can also be used in the run method, or the reference of the Thread can be found directly.
If it is created through Runnable or other methods, this cannot be used, but thread currentThread().

public  class TestDemo {
    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(){
            @Override
            public void run() {
                System.out.println(this.getId());
            }
        };

        Thread t2 = new Thread(){
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getId());
            }
        };

        t1.start();

        t2.start();
        System.out.println(Thread.currentThread().getId());
    }
}

sleep() sleep thread

In the previous blogs, and the above code, what does he do?
That is, how many ms after hibernating the current thread, continue to execute the thread, but throw an InterruptedException exception.
The current thread enters "sleep state", that is, it changes from "running state" to "blocking state".
At the end of thread hibernation, it will change to "ready" state again and wait for CPU scheduling.

After entering the sleep state, it will enter the waiting queue of the CPU until the sleep time arrives, and then put back the ready queue. After putting back the ready queue, when to run on the CPU depends on whether the scheduler will schedule immediately.

Topics: Java Multithreading