Concurrent programming - a lot of Java threads

1, Generic thread lifecycle


1. Initial state: the thread is created, but it is also allowed to be executed by the allocated cpu.
2. Runnable state: threads can allocate cpu execution.
3. Running status: the thread is being executed by the cpu.
4. Sleep state: when running, if it is blocked or waiting for an event, it will change from the running state to the sleep state and release cpu resources. If it waits for an event, it will change to the runnable state;
5. End status: the thread has completed running or an exception has occurred.

2, Thread life cycle of Java


The six states of the thread are shown in the figure above (quack quack, nice looking)
new: create a thread, allocate memory for the thread and initialize the value of its member variable;
runnable: after the start method, it will be in the ready state. At this time, the jvm completes the creation of the method call stack and the program counter, waiting for the scheduling and running of the thread;
running: obtain cpu resources and start to execute the run method;
Blocked: synchronization is blocked, and the synchronization lock is not obtained;
waiting/timed_waiting: wait for blocking

2.1 method of creating threads

(1) , inherit the thread method and override the run method

package exercise_03_0712_thread;

public class ThreadTest1 extends Thread {
    @Override
    public void run() {
        System.out.println("thread is run´Ż×");
    }

    public static void main(String[] args) {
        ThreadTest1 threadTest1 = new ThreadTest1();
        threadTest1.start();
    }
}

(2) Implement the runnable interface and rewrite the run method

package exercise_03_0712_thread;

public class ThreadTest2 implements Runnable {
    @Override
    public void run() {
        System.out.println("thread is run~");
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new ThreadTest2());
        thread.start();
    }
}

(3) Implementing threads with return values through excelorservice and Callable

package exercise_03_0712_thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class ThreadTest3 implements Callable<String> {
    private String name;
    public ThreadTest3(String name) {
        this.name = name;
    }
    @Override
    public String call() throws Exception {
        System.out.println(Thread.currentThread().getName()  + " call");
        return name;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService threadPool = Executors.newFixedThreadPool(2);
        List<Future> list = new ArrayList<>();
        for (int i = 0; i < 2; ++i) {
            Callable callable = new ThreadTest3(i + "");
            // Commit thread
            Future future = threadPool.submit(callable);
            System.out.println("submit thread :  " + i);
            list.add(future);
        }
        // Close thread pool
        threadPool.shutdown();
        // Result of traversing all threads
        for (Future future : list) {
            System.out.println("get future result: " + future.get().toString());
        }
    }
}

(4) Thread pool based

package exercise_03_0712_thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadTest4 {

    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(2);
        for (int i = 0; i < 2; ++i) {
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " is run");
                }
            });
        }
        threadPool.shutdown();
    }
}

2.2 thread startup

What is the difference between the start and run methods?
Source code:

run method: called in a thread that executes independently.

The start method does two important things in the jvm:
(1) . new a java thread, os::create_Thread();
(2) . call Thread::start to start the thread just constructed and set its state to RUNNABLE;
Therefore, the start of a thread is based on the operating system to construct the start of a thread, call back the run method, and set its state to RUNNABLE.
Code validation:
start:

run:

(1) When the start method starts a thread, the thread is in a ready state and is not running. When the run method is called, the thread will enter the running state and start to run the code in the run method. After the run method is completed, the cpu will schedule other threads.
(2) After calling start, the thread will execute in the background without waiting for the run method to complete.

2.3 thread termination

(1) . end of normal operation

That is, the run method is completed

(2) . terminate thread with exit flag

A variable is used to control the loop, and the variable is decorated with volatile to ensure thread safety.

    private volatile static boolean flag = true;
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " thread is run~");
        while (flag) {
            System.out.println("running");
        }
        System.out.println(Thread.currentThread().getName() + " thread is over~");
    }

(3) . use interrupt method to terminate the thread

a. When the thread is in the blocking state, calling interupt will throw an exception

package exercise_03_0712_thread;

public class InterruptedTest extends Thread{
    @Override
    public void run() {
        while (!isInterrupted()) {
            System.out.println("run");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        InterruptedTest interruptedTest = new InterruptedTest();
        interruptedTest.start();
        Thread.sleep(1000);
        interruptedTest.interrupt();
    }
}

Catch this exception and exit.

b. If the thread is not in the blocking state, interrupt is called. isinterrupted can be used in the thread to determine whether to terminate the thread.
The thread's default interrupted value is false;
interrupt() is called, and interrupted will become true;

package exercise_03_0712_thread;

public class InterruptedTest extends Thread{
    @Override
    public void run() {
        while (!isInterrupted()) {
            System.out.println("run");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        InterruptedTest interruptedTest = new InterruptedTest();
        interruptedTest.start();
        Thread.sleep(1000);
        interruptedTest.interrupt();
    }
}

(2) . use stop, not recommended, expired

stop kills the thread. If the thread contains a synchronized lock, it will not be released.

2.3 thread reset

The first: thread Interrupted()

package exercise_03_0712_thread;

public class InterruptedTest extends Thread{
    @Override
    public void run() {
        while (true) {
            if (isInterrupted()) {
                System.out.println("before: " + Thread.currentThread().isInterrupted());
                Thread.interrupted();//Reset, return to original state
                System.out.println("after: " + Thread.currentThread().isInterrupted());
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        InterruptedTest interruptedTest = new InterruptedTest();
        interruptedTest.start();
        Thread.sleep(1000);
        interruptedTest.interrupt();
    }
}


Second: exception
If the thread being blocked is interrupted, an exception will be thrown, and the interrupted flag of the thread will be reset.

package exercise_03_0712_thread;

public class InterruptedTest extends Thread{
    @Override
    public void run() {
        while (!isInterrupted()) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("isInterrupted: " + isInterrupted());
                break;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        InterruptedTest interruptedTest = new InterruptedTest();
        interruptedTest.start();
        Thread.sleep(1000);
        interruptedTest.interrupt();
    }
}

Tags: Concurrent Programming

Posted by davidska on Mon, 30 May 2022 18:31:46 +0530