[java basics] thread life cycle, two methods of creation and use, and thread synchronization

Keywords: Java Multithreading

catalogue

  1, Concept

1. Program, process, thread

2, Creation and use of threads

1. By inheriting the Thread class

2. By implementing the Runnable interface:

3. Related methods in Thread class

4. Thread priority

3, Thread life cycle

  1. Several states of threads

4, Thread synchronization

  1. Synchronous code block

2. Synchronization method

  1, Concept

1. Program, process, thread

  Program: a set of instructions written in a language to complete a task, and refers to a piece of static code.

  Process: it is an execution process of a program, or it can be a running program. It is a dynamic process with its own process of generation, operation and extinction ---------- that is, the life cycle.

          Thread: the process can be further subdivided into threads. When the program is running, it is an internal execution path. If a program executes multiple paths in parallel, it is multithreading.

                    As the unit of scheduling and execution, threads have independent running stacks and program technicians. Multiple threads in a process share the same memory unit and memory address space, allocate objects from the same heap and access the same objects and variables. However, multiple threads operate on shared variables and objects, which will bring security risks

2, Creation and use of threads

1. By inheriting the Thread class

Steps:

① : create a subclass of Thread

② : override the run() method in the Thrad class and declare the operation of executing this thread in the run() method

③ : instantiates the object of the current subclass

④ : call the start method in the Thread class

//Create Thread subclass
class MyThread extends Thread {

    //Override the run method in the Thread class
    public void run() {

//Declare the operation performed by this thread in the run method
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.print(Thread.currentThread().getName() + ":" + i);//Output the thread name and i of the current thread
            }
        }
    }
}

public class ThreadTest12 {
    public static void main(String[] args) {
//An object that creates a subclass of Thread
        MyThread mt = new MyThread();
//Call the start method: 1. Start the current thread; 2. Call the run () method of the current thread
        mt.start();
    }
}

There are two problems with this approach:

① We cannot start the thread by directly calling the run() method

② . start another thread. The thread that has already executed the start() method cannot be allowed to execute it. Otherwise, an error will be reported:

IllegalThreadStateException

2. By implementing the Runnable interface:

Steps:

① : create a class that implements the Runnable interface

② : override the abstract method in the Runnable class: run()

③ : create an object that implements this class

④ : pass the object of this implementation class as a parameter to the constructor of Thread class to create the object of Thread class

⑤ : call the start method in the Thread class

class MyThread implements Runnable {

    public void run() {
//Declare the operation performed by this thread in the run method
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.print(Thread.currentThread().getName() + ":" + i);//Output the thread name and i of the current thread
            }
        }

    }
}


public class ThreadTest {
    public static void main(String[] args) {
        //Create an object that implements the class
        MyThread mt = new MyThread();
        //Pass the object of this implementation class as a parameter to the thread construct, where the object of thread class is created
        Thread ta = new Thread(mt);//It reflects polymorphism
        //Call the start () method in the Thread class
        ta.start();

        Thread ta1 = new Thread(mt);//It reflects polymorphism
        ta1.start();//Start another thread and execute the run method. Note: at this time, two threads operate on the same object

    }


}

Summary: compare the two thread creation methods:

1. Priority in development: the way to implement Runnable interface

reason:

① : the implementation method has no limitation of class inheritance

② : the implementation method is more suitable for dealing with the situation that multithreading has shared data

Exercise between the two:

① : the Thread class itself also implements the run method in the Runnable interface

② : you need to override the run method

③ : all operations that the thread needs to perform must be declared in the run method

3. Related methods in Thread class

void start(): starts the thread and executes the run() method of the object

run(): the operation that the thread is scheduled to execute again

String getName(): returns the name of the current object

void setName(String name): sets the name of the current thread

static Thread currentThread(): returns the current Thread, which is this in the Thread subclass. It is usually used for the main Thread and Runnable implementation classes

static void yield(): thread concessions, pauses the thread currently executing, and gives execution opportunities to threads with the same or higher priority

                                    If there are no threads with the same priority in the queue, this method is ignored

join(): when the join method of another thread is invoked in a program execution stream, the calling thread will be blocked until the join method joined by the join method is executed.

Static void sleep (long millis):

① : enable the current active thread to give up control over the cpu within the specified time, so that other threads have the opportunity to be executed, and queue up again when the time is up

② : throw InterruptedException exception

stop(): force the end of the thread declaration cycle. It is not recommended

boolean   isAlive: determines whether the thread is still alive

4. Thread priority

Threads with the same priority form a first in first out queue (first in first out service) and use the time slice strategy

For priority threads, the preemptive strategy of priority scheduling is adopted (high priority threads preempt CPU)

Priority level of thread:

MAX_PRIORITY: 10

MIN_PRIORITY: 1

NORM_PRIORITY: 5

Relevant methods involved:

getPriority() returns the priority registration of the related thread

setPriority (int newPriority) sets the priority registration of related threads  

Note:

When a thread is created, it inherits the priority of the parent thread

For low priority, the probability of scheduling is low, not necessarily after the completion of high priority

3, Thread life cycle

  1. Several states of threads

4, Thread synchronization

Preamble: when a thread is executing but has not completed the operation,         The participation of other threads will lead to thread safety problems, which can be solved in the following two ways (idea: when a thread is operating shared data, let other threads not participate in it until thread a completes its operation, so that even if thread a is blocked, it cannot be changed)

  1. Synchronous code block

Synchronized (synchronized monitor){   // Synchronization monitor: commonly known as lock. An object of any class can be called a lock. Multiple threads must share a lock!

//Code to be synchronized

}

① : combine synchronous code blocks by inheriting Thread subclasses

//Create Thread subclass
class MyThread extends Thread {

    //Override the run method in the Thread class
    public void run() {

synchroinzed(this){ //You can use the current object, but use this carefully in inheriting the Thread class
//Declare the operation performed by this thread in the run method
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.print(Thread.currentThread().getName() + ":" + i);//Output the thread name and i of the current thread
                }
            }
        }
    }
}

public class ThreadTest12 {
    public static void main(String[] args) {
//An object that creates a subclass of Thread
        MyThread mt = new MyThread();
//Call the start method: 1. Start the current thread; 2. Call the run () method of the current thread
        mt.start();
    }
}

② : the method of implementing Runnable interface is combined with synchronous code block

class Window1 implements Runnable{
    private int ticket = 100;
    Object obj = new Object();
    @Override
    public void run() {
        while (true){
            synchronized(this) { //You can also use the current object. this: the only object of window1
                if (ticket > 0) {

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + ":" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}

public class WindowTest1 {
    public static void main(String[] args) {
        Window1  w = new Window1();
        Thread t =new Thread(w);
        Thread t1 =new Thread(w);
        Thread t2=new Thread(w);
        t.start();
        t1.start();
        t2.start();
    }
}

2. Synchronization method

① : the synchronization method is combined by implementing the Runnable interface

//Using synchronization method to solve the thread safety problem of implementing Runnable interface
 
class Window3 implements Runnable {
    private int ticket = 1000;

    @Override
    public void run() {
        while (true) {
            show();
        }
    }

    public synchronized void show() { //Sync monitor: this
        //  synchronized (this) {
        if (ticket > 0) {
/*                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }*/
            System.out.println(Thread.currentThread().getName() + ":" + ticket);
            ticket--;
        }
        //   }
    }

}


public class WindowTest3 {
    public static void main(String[] args) {
        Window3 w = new Window3();
        Thread t = new Thread(w);
        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        t.start();
        t1.start();
        t2.start();
    }
}

② : combine synchronization methods by inheriting Thread class

/**Using synchronous methods to deal with Thread safety problems in the way of inheriting Thread class
 *
 * Summary of synchronization methods:
 * 1,The synchronization method still involves the synchronization monitor, but we don't need to declare it explicitly
 * 2,Non static synchronization method. The synchronization monitor is this
 *    Static synchronization method: the synchronization monitor is the current class itself
 *
 */
class Window4 extends Thread {

    private static int ticket = 100;

    //Become unique, use static


    @Override
    public void run() {
        while (true) {
            show();
        }
    }

    private static synchronized void show() {//Synchronization monitor: Window.class
        //private synchronized void show() / / this method is wrong. Three objects come in
        if (ticket > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "Ticket No.:" + ticket);
            ticket--;
        }
    }
}

public class WindowTest4 {
    public static void main(String[] args) {
        Window4 w = new Window4();
        Window4 w1 = new Window4();
        Window4 w2 = new Window4();

        w.setName("Window 1");
        w1.setName("Window 2");
        w2.setName("Window 3");

        w.start();
        w1.start();
        w2.start();
    }
}

 

Posted by mooshuligan on Sat, 06 Nov 2021 00:29:16 -0700