day24 multithreading (inheriting Thread class & implementing Runnable interface) & Thread safety (synchronous code block & Lock lock)

Posted by ashmo on Mon, 21 Feb 2022 14:00:15 +0100

Multithreading overview

Process:
The running program is an independent unit for the system to allocate and call resources. Each process has its own memory space and resources.
Thread:
It is a single sequential control flow of a process, or a separate execution path
If a process has only one execution path, it is called single thread
If a process has multiple execution paths, it is called multithreading
Threads are contained in processes

The first way to create a Thread: inherit the Thread class
1. Create a custom class to inherit the Thread class
2. This class needs to override the run method in the Thread class
When the thread starts, the code logic executed is only the code logic of the run() method
3. Create thread objects based on this class
4. Start thread

Precautions:
1. The start thread calls the start() method
2. The start sequence of threads has no effect on the results

The difference between calling start() and calling run()
The run() method only encapsulates the code executed by the thread, but there is no difference between calling run() directly and calling ordinary methods
To call the start() method, first start a thread separately, and then the JVM calls the run() method in the thread class

package com.shujia.wyh.day24;

public class MyThreadDemo2 {
    public static void main(String[] args) {
        //Simulate multithreading environment
        //Create at least 2 or more thread objects
        MyThread1 myThread1 = new MyThread1();
        MyThread1 myThread2 = new MyThread1();

        //Start thread
        myThread1.start();
        myThread2.start();

    }
}

class MyThread1 extends Thread{
    @Override
    public void run() {
        //Write the logical code we want the thread to execute
        for(int i=1;i<200;i++){
            System.out.println(i);
        }
    }
}

Name the thread through the construction method:
Thread(String name) assigns a new thread object.

Gets the name of the thread
public final String getName() returns the name of this thread

package com.shujia.wyh.day24;

public class MyThreadDemo3 {
    public static void main(String[] args) {
        //Create thread object
        //Name the thread through the construction method
        //Since we want to simulate a multithreaded environment, the number of threads created is 2 or more
        MyThread2 t1 = new MyThread2();
        MyThread2 t2 = new MyThread2();
        MyThread2 t3 = new MyThread2();
        //public final void setName(String name) changes the name of this thread to be equal to the parameter name.
        t1.setName("Xiao Ming");
        t2.setName("Xiao Wang");
        t3.setName("Xiao Zhou");
        //Start thread
        t1.start();
        t2.start();
        t3.start();

    }
}

class MyThread2 extends Thread {
    public MyThread2() {
    }

    public MyThread2(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 1; i <= 200; i++) {
            System.out.println(getName() + ":" + i);
        }
    }
}

Thread sleep public static void sleep (long miles)

package com.shujia.wyh.day24;

public class ThreadSleepDemo {
    public static void main(String[] args) {
        MySleepThread t1 = new MySleepThread();
        MySleepThread t2 = new MySleepThread();
        MySleepThread t3 = new MySleepThread();

        //Set a name for the thread
        t1.setName("Xiao Ming");
        t2.setName("Xiao Wang");
        t3.setName("Xiao Zhou");

        //Start thread
        t1.start();
        t2.start();
        t3.start();
    }
}

class MySleepThread extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 200; i++) {
            System.out.println(getName() + ":" + i);
            //Method of adding sleep
            //public static void sleep(long millis)
            //Stop for 1 second, 1 second = 100 milliseconds
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

Join thread public final void join()
Other threads wait for the thread that calls the join to execute before executing.

Note:
The call of join must be after start.

package com.shujia.wyh.day24;

public class ThreadJoinDemo {
    public static void main(String[] args) {
        MyJoinThread t1 = new MyJoinThread();
        MyJoinThread t2 = new MyJoinThread();
        MyJoinThread t3 = new MyJoinThread();

        //Set a name for the thread
        t1.setName("Xiao Ming");
        t2.setName("Xiao Wang");
        t3.setName("Xiao Zhou");

        //Start thread
        t1.start();

        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        t2.start();
        t3.start();
    }
}

class MyJoinThread extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 200; i++) {
            System.out.println(getName() + ":" + i);
        }
    }
}

Comity thread public static void yield()
Pauses the currently executing thread object and executes other threads
In order to make it more harmonious for multiple threads to run at one time.

package com.shujia.wyh.day24;

public class ThreadYieldDemo {
    public static void main(String[] args) {
        //Create 2 Thread objects to simulate multithreading
        MyYieldThread t1 = new MyYieldThread();
        MyYieldThread t2 = new MyYieldThread();

        //Name the thread
        t1.setName("Xiao Ming");
        t2.setName("Xiao Wang");

        //Start thread
        t1.start();
        t2.start();
    }
}

class MyYieldThread extends Thread{
    @Override
    public void run() {
        for(int i=1;i<=200;i++){
            System.out.println(getName()+":"+i);
            Thread.yield();
        }
    }
}

Background thread: (daemon thread) public final void setDaemon(boolean on)

There are two kinds of threads in Java: user thread and daemon thread

User thread: before learning multithreading, the running threads are user threads

Daemon thread: the so-called daemon thread refers to a general service thread provided in the background when the program is running. For example, the garbage collection thread is a daemon thread, and this thread does not necessarily exist, so conversely, as long as the program has a daemon thread, the program will not terminate.

Note:
1. The daemon thread must be set before starting
2. When the running program has only one thread and this thread is a guard thread, the Java virtual machine exits (the program stops)

package com.shujia.wyh.day24;

public class ThreadDaemonDemo {
    public static void main(String[] args) {
        //Create 3 threads
        MyDaemonThread t1 = new MyDaemonThread();
        MyDaemonThread t2 = new MyDaemonThread();
        MyDaemonThread t3 = new MyDaemonThread();

        //Name the thread
        t1.setName("Liu Bei"); //This thread ends and the daemon thread ends
        t2.setName("Guan Yu");
        t2.setDaemon(true);
        t3.setName("Fei Zhang");
        t3.setDaemon(true);

        //Start thread
        t1.start();
        t2.start();
        t3.start();
    }
}

class MyDaemonThread extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 200; i++) {
            System.out.println(getName() + ":" + i);
        }
    }
}

Interrupt thread public void interrupt()

When sleep is interrupted, the code behind the run method continues to execute. After execution, an exception is thrown

package com.shujia.wyh.day24;
import java.util.Date;

public class ThreadStopDemo {
    public static void main(String[] args) {
        MyStopThread t1 = new MyStopThread();

        t1.setName("floret");

        t1.start();

        try {
            Thread.sleep(3000);
            t1.interrupt(); //When sleep is interrupted, the code behind the run method continues to execute. After execution, an exception is thrown
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

class MyStopThread extends Thread {
    @Override
    public void run() {
        System.out.println("Start execution time:" + new Date());

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

        System.out.println("End time:" + new Date());
    }
}

Implementation scheme 2 of multithreading: implement Runnable interface
1. Customize a class to implement Runnable interface
2. Implement the run() method
3. Create custom class objects
4. Create a Thread object and pass the custom object as a parameter to the construction method

public static Thread currentThread() returns a reference to the thread object currently executing.
        System.out.println(Thread.currentThread().getName());

package com.shujia.wyh.day24;

public class MyRunnableDemo1 {
    public static void main(String[] args) {
        //Create custom class object
        MyRunnable1 myRunnable1 = new MyRunnable1();

        //Create 2 Thread objects
        Thread t1 = new Thread(myRunnable1);
        Thread t2 = new Thread(myRunnable1);

        //Name the thread
        t1.setName("Xiao Ming");
        t2.setName("Xiao Wang");

        t1.start();
        t2.start();
    }
}

class MyRunnable1 implements Runnable {
    @Override
    public void run() {
        for (int i = 1; i <= 200; i++) {
            //Since there is no getName() method in the Runnable interface, the name of the thread object cannot be obtained here
            //Indirectly, we can get the object of the current Thread first, and then call the getName() method in the Thread class
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}

Thread safety
To solve this problem, we must find out what causes the problem:
(the three points summarize whether thread safety problems will occur, which are indispensable)
1. Is there a multithreaded environment
2. Whether there are shared data / shared variables
3. Are there multiple statements operating shared data / shared variables

Problem solving ideas:
If there is a way to package the code of multiple statements operating shared data into a whole, it is OK if other threads cannot enter when one thread is executing. Until a thread executes the run method once, other threads can enter the execution.

Java provides a mechanism for us to use to solve the problem of thread safety: synchronous safety mechanism

Solution 1: synchronize code blocks
Statement format:
Synchronized (object) {code that needs to be synchronized;}
1. The object here is any object, but it should be noted that the lock object between multiple threads should be the same
2. Need synchronization: multiple statements operate the code of shared data

Benefits of synchronization:
It solves the security problem of multithreading

Disadvantages of synchronization:
Adding a synchronization code block is equivalent to adding a lock. We will judge it every time we enter the synchronization code block, which reduces our execution efficiency.

Example: a movie theater is currently showing a New Year blockbuster, with a total of 100 tickets, and it has three ticket windows. Please design a program to simulate the ticket sales of the movie theater.

package com.shujia.wyh.day24;

public class SellTicketDemo4 {
    public static void main(String[] args) {
        //1. Create custom class object
        TicketWindow4 ticketWindow2 = new TicketWindow4();

        //2. Create three thread objects and simulate three windows
        Thread window1 = new Thread(ticketWindow2);
        Thread window2 = new Thread(ticketWindow2);
        Thread window3 = new Thread(ticketWindow2);

        //3. Name the thread object
        window1.setName("Window 1");
        window2.setName("Window 2");
        window3.setName("Window 3");

        //4. Start thread
        window1.start();
        window2.start();
        window3.start();
    }
}

class TicketWindow4 implements Runnable{
    private int tickets = 500;
    private Object object = new Object();

    @Override
    public void run() {
        while (true) {
            synchronized (object){
                if (tickets > 0) {
                    //In order to simulate a more realistic ticket selling scenario, we add delay
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "In the process of sale" + (tickets--) + "Ticket");

                }
            }
        }
    }
}

Solution 2: Lock lock
Lock (Interface)
Specific subclass: Class ReentrantLock
Lock
unlock() release lock

package com.shujia.wyh.day25;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SellTicketDemo3 {
    public static void main(String[] args) {
        TicketWindow3 ticketWindow1 = new TicketWindow3();

        //Use the Thread class to create multiple Thread objects
        Thread window1 = new Thread(ticketWindow1);
        Thread window2 = new Thread(ticketWindow1);
        Thread window3 = new Thread(ticketWindow1);

        //Name the thread
        window1.setName("Window 1");
        window2.setName("Window 2");
        window3.setName("Window 3");

        //Start thread
        window1.start();
        window2.start();
        window3.start();

    }
}


class TicketWindow3 implements Runnable {
    private int tickets = 100;
    //Create lock object
    private Lock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            lock.lock();
            if (tickets > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + "In the process of sale" + (tickets--) + "Ticket");
            }
            lock.unlock();
        }

    }
}

Topics: Java