Java multithreading (note version with code and video links)

Posted by phpusr on Sun, 16 Jan 2022 10:09:39 +0100

##Write a blog for the first time and share your study notes with you
##The video link points to the teaching video of Madness (for free)
##If there are mistakes, please criticize and correct them
##If infringement is involved, please contact me to delete it

Multithreading

The thread is not necessarily executed immediately after it is started, and is scheduled by the CPU

1. Multi thread creation method

1.1 Thread creation method 1: inherit the Thread class, rewrite the Thread body of the run method, and call start();

/*
   The thread is not necessarily executed immediately after it is started, and the cpu arranges the scheduling
 */
//Thread creation method 1: inherit the thread class, rewrite the thread body of the run method, and call start();
//Inherit Thread class
public class TestThread1 extends  Thread{
    //Override the run method thread body
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("Jay " + i);
        }
    }

    public static void main(String[] args) {
        //Create a thread object
        TestThread1 testThread1 = new TestThread1();
        //Call the start() method to start the thread
        testThread1.start();
        for (int i = 0; i < 20; i++) {
            System.out.println("Soul " + i);
        }
    }
}

Video link

package Jay;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;

/*
Practice Thread to realize multi-threaded synchronous downloading of pictures
 */
public class TestThread2 extends Thread{
    private String url;
    private String name;
    public TestThread2(String url, String name){
        this.url = url;
        this.name = name;
    }
    //Thread executor for downloading pictures
    public void run(){
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.downloader(url, name);
        System.out.println(name + " File downloaded successfully");
    }

    public static void main(String[] args) {
        TestThread2 t1 = new TestThread2("https://cdn.jsdelivr.net/gh/filess/img17@main/2021/05/07/1620371242789-b286c6f7-a06c-48c7-a53b-3a86d18cea97.png", "p1.png");
        TestThread2 t2 = new TestThread2("https://cdn.jsdelivr.net/gh/filess/img16@main/2021/05/07/1620377761880-1d4715d4-482c-4d52-a5aa-210a1a354c77.png", "p2.png");
        TestThread2 t3 = new TestThread2("https://cdn.jsdelivr.net/gh/filess/img8@main/2021/05/07/1620377156603-8b53ee53-8de0-4f81-b667-3df6ce555064.png", "p3.png");

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

}
//Downloader
class WebDownloader{
    public void downloader(String url, String name){
        try {
            FileUtils.copyURLToFile(new URL(url), new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO Abnormal, downloader There was a problem downloading");
        }
    }
}

Video link

1.2 create thread method 2: implement the runnable interface, rewrite the run method, and the execution thread needs to drop into the runnable interface implementation class and call the start method

//Create thread method 2: implement the runnable interface. Rewrite the run method. The execution thread needs to drop into the runnable interface implementation class and call the start method
public class TestThread3 implements Runnable{
    //Override the run method thread body
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("Jay " + i);
        }
    }

    public static void main(String[] args) {
        //Create an implementation class object for the runnable interface
        TestThread3 testThread3 = new TestThread3();
        //Create a thread object and start my thread (proxy) through the thread object
        new Thread(testThread3).start();
        for (int i = 0; i < 20; i++) {
            System.out.println("Soul " + i);
        }
    }
}

Video link

When multiple threads operate on the same object at the same time, the thread is unsafe and the data is disordered

//When multiple threads operate on the same object at the same time, the thread is unsafe and the data is disordered
//Example of buying a train ticket
public class TestThread4 implements Runnable{
    private int ticketNums = 10;

    public void run(){
        while (true){
            if (ticketNums <= 0){
                break;
            }
            /*try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
            System.out.println(Thread.currentThread().getName() + "-->Got the second" + ticketNums-- + "ticket");

        }
    }

    public static void main(String[] args) {
        TestThread4 ticket = new TestThread4();

        new Thread(ticket, "Xiao Ming").start();
        new Thread(ticket, "Xiao Hong").start();
        new Thread(ticket, "Xiao Huang").start();

    }
}

Video link

Tortoise and rabbit race


import kotlin.reflect.jvm.internal.impl.descriptors.Visibilities;

//Simulated tortoise rabbit race
public class Race implements Runnable{
    private static String winner;

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            if (Thread.currentThread().getName().equals("rabbit") && i % 60 == 0)
            {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if (gameOver(i)) break;
            System.out.println(Thread.currentThread().getName() + "-->Run away" + i + "step");
        }
    }

    //Judge whether to complete the game
    private boolean gameOver (int step){
        if (winner != null){
            return true;
        }
        if (step >= 100) {
            winner = Thread.currentThread().getName();
            System.out.println("Winner is " + winner);
            return true;
        }
        return  false;

    }

    public static void main(String[] args) {
        Race race = new Race();
        new Thread(race, "rabbit").start();
        new Thread(race, "tortoise").start();
    }


}

Video link

1.3 thread creation method 3: implement the callable interface

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
//Thread creation mode 3: implement the callable interface
/*
callable Benefits of
1,You can define the return value
2,Exceptions can be thrown
 */
public class TestCallable implements Callable<Boolean> {
    private String url;
    private String name;
    public TestCallable(String url, String name){
        this.url = url;
        this.name = name;
    }
    //Thread executor for downloading pictures
    public Boolean call(){
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.downloader(url, name);
        System.out.println(name + " File downloaded successfully");
        return true;
    }

    public static void main(String[] args) {
        TestCallable t1 = new TestCallable("https://cdn.jsdelivr.net/gh/filess/img17@main/2021/05/07/1620371242789-b286c6f7-a06c-48c7-a53b-3a86d18cea97.png", "p1.png");
        TestCallable t2 = new TestCallable("https://cdn.jsdelivr.net/gh/filess/img16@main/2021/05/07/1620377761880-1d4715d4-482c-4d52-a5aa-210a1a354c77.png", "p2.png");
        TestCallable t3 = new TestCallable("https://cdn.jsdelivr.net/gh/filess/img8@main/2021/05/07/1620377156603-8b53ee53-8de0-4f81-b667-3df6ce555064.png", "p3.png");

        //Create execution service:
        ExecutorService ser = Executors.newFixedThreadPool(3);

        //Submit for execution
        Future<Boolean> r1 = ser.submit(t1);
        Future<Boolean> r2 = ser.submit(t2);
        Future<Boolean> r3 = ser.submit(t3);
        //Shut down service
        ser.shutdownNow();
    }

}
//Downloader
class WebDownloader{
    public void downloader(String url, String name){
        try {
            FileUtils.copyURLToFile(new URL(url), new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO Abnormal, downloader There was a problem downloading");
        }
    }
}

Video link

2. Static proxy mode

package Jay;
/*
Static proxy:
1,Both real objects and proxy objects implement an interface
2,The proxy object needs a proxy role
 */
public class StaticProxy{
    public static void main(String[] args) {
        new MarryCompany(new you()).happyMarry();
    }
}
interface Marry{
    public void happyMarry();
}

//Real character marriage
class you implements Marry{
    @Override
    public void happyMarry() {
        System.out.println("Yuanbao is married");
    }
}

//Wedding company agent
class MarryCompany implements  Marry{
    private Marry target;

    public MarryCompany(Marry target) {
        this.target = target;
    }

    @Override
    public void happyMarry() {
        berfore();
        this.target.happyMarry();//This is the real object
        after();
    }

    private void after() {
        System.out.println("Closing payment");
    }

    private void berfore() {
        System.out.println("Layout site");
    }
}

Video link

3. Lamda expression

3.1 why lamda representation

- Avoid too many anonymous inner class definitions
- Make the code look concise, remove meaningless code, and leave only the core logic
- Its essence belongs to the concept of functional programming

3.2 definition of functional interface

- Any interface that contains only one abstract method is a functional interface
- For functional interfaces, we can lamda Expression to create an object of the interface
package thread.lamda;

/*
Derivation of lamda expression
 */
public class TestLamda01 {
    //3. Static internal class
    static class Like2 implements ILike{

        @Override
        public void lamda() {
            System.out.println("I like lamda2!");
        }
    }
    public static void main(String[] args) {
        ILike like = new Like();
        like.lamda();

        like = new Like2();
        like.lamda();
        //4. Local internal class
        class Like3 implements ILike{

            @Override
            public void lamda() {
                System.out.println("I like lamda3!");
            }
        }
        like = new Like3();
        like.lamda();
        //5. Anonymous inner class. There is no class name. You must use the interface or parent class
        like = new ILike() {
            @Override
            public void lamda() {
                System.out.println("I like lamda4!");
            }
        };
        like.lamda();

        //6. Simplify with lamda
        like = ()->{
            System.out.println("I like lamda5!");
        };
        like.lamda();
    }
}

//1. Define a functional interface
interface ILike{
    void lamda();
}

//2. Implementation class
class Like implements ILike{

    @Override
    public void lamda() {
        System.out.println("I like lamda!");
    }
}
package thread.lamda;

public class TestLamda02 {
    //Static inner class
    static class love2 implements ILove{
        @Override
        public void love(int a) {
            System.out.println("I love" + a);
        }
    }

    public static void main(String[] args) {
        //Common class implementation
        ILove love = new love();
        love.love(1);
        //Static inner class implementation
        love = new love2();
        love.love(2);
        //Local inner class
        class love3 implements ILove{
            @Override
            public void love(int a) {
                System.out.println("I love" + a);
            }
        }
        new love3().love(77);
        //Anonymous Inner Class 
        love = new ILove() {
            @Override
            public void love(int a) {
                System.out.println("I love" + a);
            }
        };
        love.love(3);
        //lamda simplification
        love = (int a)->{
            System.out.println("I love" + a);
        };
        love.love(4);
    }
}

interface ILove{
    void love(int a);
}

class love implements ILove{

    @Override
    public void love(int a) {
        System.out.println("I love" + a);
    }
}

3.3 simplified form of lamda

//Simplified form 1
love = (a) -> {
	System.out.println("I love" + a);
};
//Simplified form 2 (parameter < = 1)
love = a -> {
	System.out.println("I love" + a);
};
//Simplified form 3 (only one line of code)
love = a -> System.out.println("I love" + a);

Video link

4. Thread status and method

Once a thread enters a dead state, it cannot be started again

4.1 five states

* Create status( new)
* Ready status( start)
* running state 
* Blocking state( sleep,wait)
* Death state

4.2 threading method

4.3 stopping threads

- It is recommended that the thread stop itself (dead loop is not recommended)
- It is recommended to use a flag bit to terminate the variable (when flag= false,Terminate the thread)
- Do not use stop perhaps destroy Etc. outdated or JDK Method not recommended
package thread.methods;
//Test stop
public class TestStop implements Runnable{
    //1. Set a flag bit
    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while (flag){
            System.out.println("run ....... Thread" + i++);
        }
    }
    //2. Set a public method to stop the thread and convert the flag bit
    public void stop(){
        this.flag = false;
    }

    public static void main(String[] args) {
        TestStop testStop = new TestStop();

        new Thread(testStop).start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("main" + i);
            if (i == 900){
                testStop.stop();
                System.out.println("The thread has stopped");
            }
        }
    }
}

Video link

4.4 thread sleep

* sleep(Time) specifies the number of milliseconds the current thread is blocking
* sleep There is an exception InterruptedException
* sleep When the time is up, the thread enters the ready state
* sleep Can simulate network delay, countdown, etc
* Every object has a lock, sleep The lock will not be released

Video link

4.5 yield

package thread.methods;
//Test comity thread
public class TestYield {
    public static void main(String[] args) {
        //lamda expression
        Runnable myYield = ()->{
            System.out.println(Thread.currentThread().getName() + "Thread starts execution");
            Thread.yield();
            System.out.println(Thread.currentThread().getName() + "End of thread running");
        };
        new Thread(myYield, "a").start();
        new Thread(myYield, "b").start();

    }
}

//class MyYield implements Runnable{
//
//    @Override
//    public void run() {
//        System.out.println(Thread.currentThread().getName() + "thread starts execution");
//        Thread.yield();
//        System.out.println(Thread.currentThread().getName() + "end of thread running");
//    }
//}

Video link

4.6 merge threads (Join)

* Join Merge threads. After this thread completes execution, execute other threads. Other threads are blocked
* Imagine jumping in line
package thread.methods;

//Test join method
public class TestJoin implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("VIP coming" + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        //Start our thread
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();

        //Main thread
        for (int i = 0; i < 500; i++) {
            if (i == 100){
                thread.join();
            }
            System.out.println("main" + i);
        }
    }
}

Video link

4.7 observing thread status

package thread.state;

public class TestState {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("/");
        });
        //Observation status (new)
        Thread.State state = thread.getState();
        System.out.println(state);
        //run
        thread.start();
        state = thread.getState();
        System.out.println(state);

        //As long as the thread does not terminate, it always outputs the state
        while (state != Thread.State.TERMINATED){
            Thread.sleep(100);
            state = thread.getState();//Update thread status
            System.out.println(state);
        }

    }
}

Video link

5. Thread priority

Low priority only means that the probability of obtaining scheduling is low, not that it will not be called if the priority is low, which depends on CPU scheduling

* The priority of a thread is expressed in numbers, ranging from 1~10
	* Thread.MIN_PRIORITY = 1
	* Thread.MAX_PRIORITY =10
	* Thread.NORM_PRIORITY = 5
* Change or get priority in the following ways
	* getPriority()
	* setPriority(int xxx)
package thread.state;
//Test thread priority
public class TestPriority {
    public static void main(String[] args) {
        //Main thread priority
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());

        //Create thread
        MyPriority myPriority = new MyPriority();
        Thread t1 = new Thread(myPriority);
        Thread t2 = new Thread(myPriority);
        Thread t3 = new Thread(myPriority);
        Thread t6 = new Thread(myPriority);

        t1.setPriority(10);
        t1.start();
        t2.start();
        t3.setPriority(8);
        t3.start();
        t6.setPriority(1);
        t6.start();
    }

}

class MyPriority implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "-->" +Thread.currentThread().getPriority());
    }
}

Video link

6. daemon thread

* Threads are divided into user threads and daemon threads
* The virtual machine must ensure that the user thread has completed execution( main)
* The virtual machine does not have to wait for the daemon thread to complete execution, such as recording operation logs in the background, monitoring memory, garbage collection and so on( gc)
package thread.methods;
//Test daemon thread
public class TestDaemon {
    public static void main(String[] args) {
        Love love = new Love();
        You you = new You();
        Thread thread = new Thread(love);
        thread.setDaemon(true);//The default is false, indicating that it is a user thread
        thread.start();//Daemon thread start
        new Thread(you).start();//User thread start
    }
}
//Daemon thread
class Love implements Runnable{
    @Override
    public void run() {
        while (true){
            System.out.println("Love is with you");
        }
    }
}
//User thread
class You implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 36500; i++) {
            System.out.println("Alone, company");
        }
        System.out.println("-====goodbye!world!====-");
    }
}

Video link

7. Thread synchronization

Concurrency: the same object is operated by multiple threads at the same time, forming conditions: queue and lock (lock mechanism synchronized)

* Tens of thousands of people robbed 100 tickets at the same time
* Two banks withdraw money at the same time

Video link

7.1 three unsafe cases

package thread.syn;
//Unsafe ticket buying
//Thread unsafe, negative number
public class UnsafeBuyTicket {
    public static void main(String[] args) {
        BuyTicket buyTicket = new BuyTicket();

        new Thread(buyTicket, "Xiao Ming").start();
        new Thread(buyTicket, "Xiao Hong").start();
        new Thread(buyTicket, "Xiao Jie").start();
    }
}

class BuyTicket implements Runnable{
    private  int ticketNums = 10;
    boolean  flag = true;
    public void run() {
        while (flag){
            if (ticketNums <= 1) flag = false;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " Get" + ticketNums--);
        }
    }
}
package thread.syn;
//Bank withdrawal
public class UnsafeBank {
    public static void main(String[] args) {
        Account account = new Account(100000, "Marriage fund");
        Drawing you = new Drawing(account, 5000, "yourself");
        Drawing yourWife = new Drawing(account, 10000, "yourWife");
        you.start();
        yourWife.start();
    }
}
class Account{
    int money;
    String name;
    public Account(int money, String name) {
        this.money = money;
        this.name = name;
    }
}
class Drawing extends Thread{
    Account account;
    int drawingMoney;
    int nowMoney;
    public Drawing(Account account, int drawingMoney, String name){
        super(name);
        this.account = account;
        this.drawingMoney = drawingMoney;
    }
    @Override
    public void run() {    
       if (account.money - drawingMoney < 0){
            System.out.println(this.getName()+ "Sorry, your credit is running low");
            return;
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        account.money =  account.money - drawingMoney;
        nowMoney = nowMoney + drawingMoney;
        System.out.println(account.name + "The balance is" + account.money);
        //Thread.currentThread().getName() == this.getName();
        System.out.println(this.getName() + "The money in hand is" + nowMoney);
        
   }
}
package thread.syn;
//form
import java.util.ArrayList;
import java.util.List;

public class UnsafeList {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < 100000; i++) {
            new Thread(()->{list.add(Thread.currentThread().getName());}).start();
        }
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

Video link

7.2 synchronization method

The synchronization listener of the public synchronized void method(int args) {} synchronization method is this, that is, the object itself or class

package thread.syn;
//Buy a ticket safely
public class UnsafeBuyTicket {
    public static void main(String[] args) {
        BuyTicket buyTicket = new BuyTicket();

        new Thread(buyTicket, "Xiao Ming").start();
        new Thread(buyTicket, "Xiao Hong").start();
        new Thread(buyTicket, "Xiao Jie").start();
    }
}
class BuyTicket implements Runnable{
    private  int ticketNums = 10;
    boolean  flag = true;
    public void run() {
        while (flag){
            buy();
        }
    }
    //The synchronized synchronization method locks this
    private synchronized void buy() {
        if (ticketNums <= 0) {flag = false;return;}
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " Get" + ticketNums--);
    }
}

7.3 synchronization block

synchronized (Obj) {} Obj can be any object, but it is recommended to use shared resources (addition, deletion and modification) as the synchronization monitor

* Synchronization monitor execution
	* The first thread accesses, locks the synchronization monitor, and executes the code in it.
	* The second thread accesses and finds that the synchronization monitor is locked and cannot be accessed
	* After the first thread is accessed, unlock the synchronization monitor
	* The second thread accesses, finds that the synchronization monitor has no lock, and then locks and accesses
package thread.syn;

public class UnsafeBank {
    public static void main(String[] args) {
        Account account = new Account(100000, "Marriage fund");
        Drawing you = new Drawing(account, 5000, "yourself");
        Drawing yourWife = new Drawing(account, 10000, "yourWife");
        you.start();
        yourWife.start();
    }
}
class Account{
    int money;
    String name;
    public Account(int money, String name) {
        this.money = money;
        this.name = name;
    }
}
class Drawing extends Thread{
    Account account;
    int drawingMoney;
    int nowMoney;
    public Drawing(Account account, int drawingMoney, String name){
        super(name);
        this.account = account;
        this.drawingMoney = drawingMoney;
    }
    @Override
    public void run() {
        synchronized (account){
            if (account.money - drawingMoney < 0){
                System.out.println(this.getName()+ "Sorry, your credit is running low");
                return;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            account.money =  account.money - drawingMoney;
            nowMoney = nowMoney + drawingMoney;
            System.out.println(account.name + "The balance is" + account.money);
            //Thread.currentThread().getName() == this.getName();
            System.out.println(this.getName() + "The money in hand is" + nowMoney);
        }
    }
}
package thread.syn;

import java.util.ArrayList;
import java.util.List;

public class UnsafeList {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < 100000; i++) {
            new Thread(()->{
                synchronized (list){
                    list.add(Thread.currentThread().getName());}
                }).start();
        }
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

Video link

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>(); List with lock

package thread.syn;

import java.util.concurrent.CopyOnWriteArrayList;

//Testing a collection of JUC security types
public class TestJUC {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()-> list.add(Thread.currentThread().getName())).start();
        }
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());

    }
}

Video link

7.4 deadlock

Deadlock: a synchronization block has "locks of more than two objects" at the same time

package thread.syn;
//Deadlock: multiple threads hold each other's required resources, and then form a deadlock
public class DeadLock {
    public static void main(String[] args) {
        MakeUp g1 = new MakeUp(0,"Cinderella");
        MakeUp g2 = new MakeUp(1,"Snow White");
        g1.start();
        g2.start();
    }
}
//Lipstick
class LipStick{}
//mirror
class Mirror{}
class MakeUp extends Thread {
    //Only one resource is needed, which is guaranteed by static
    static LipStick lipStick = new LipStick();
    static Mirror mirror = new Mirror();
    int choice;//choice
    String name;//People who use cosmetics
    MakeUp(int choice, String name) {
        this.choice = choice;
        this.name = name;
    }
    @Override
    public void run() {
        try {
            makeup();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //Make up and hold each other's resources
    private void makeup() throws InterruptedException {
        if (choice == 0) {
            synchronized (lipStick) {//Get lipstick lock
                System.out.println(this.name + "Get lipstick");
                Thread.sleep(1000);
            }
            synchronized (mirror) {//Get the lock of the mirror
                System.out.println(this.name + "Get the lock of the mirror");
            }
        } else {
            synchronized (mirror) {//Get the lock of the mirror
                System.out.println(this.name + "Get the lock of the mirror");
                Thread.sleep(2000);
                }
            synchronized (lipStick) {//Get lipstick lock
                System.out.println(this.name + "Get lipstick lock");
            }
        }
    }
}

Video link

7.5 explicit LOCK

package thread.syn;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
    public static void main(String[] args) {
        TestLock2 testLock2 = new TestLock2();
        new Thread(testLock2, "Xiao Ming").start();
        new Thread(testLock2, "Xiao Jie").start();
        new Thread(testLock2, "Xiao Wang").start();
    }
}
class TestLock2 implements Runnable{
    private int tickNums = 10;
    boolean flag = true;
    private final ReentrantLock reentrantLock = new ReentrantLock();
    @Override
    public void run() {
        try{
            reentrantLock.lock();
            while (flag){
                if (tickNums <= 0 ){
                    flag = false;
                    return;
                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "Got" + tickNums--);
            }
        }finally {
            reentrantLock.unlock();
        }
    }
}

Video link

8. Thread collaboration

Producer consumer problem: producers and consumers share the same resource, and producers and consumers are interdependent and conditional on each other

effectMethod name
It means that the thread waits until other threads notify it. Unlike sleep, it will release the lockwait()
Specifies the number of milliseconds to waitwait(long timeout)
Wake up a waiting threadnotify()
Wake up all threads calling the wait() method on the same object, and the threads with high priority are scheduled firstnotifyAll()

8.1 solution 1

Concurrent collaboration model "producer / consumer model" -- > management method

* Producer: the module responsible for production data (may be method, object, thread, process)
* Consumer: module responsible for processing data (may be method, object, thread, process)
* Buffer: consumers cannot directly use the producer's data. There is a "buffer" between them

The producer puts the produced data into the buffer, and the consumer takes out the data from the buffer
Video link

package thread.itc;
//Test: producer consumer model -- > tube process method
public class TestPC {
    public static void main(String[] args) {
        SynContainer container = new SynContainer();
        new Producer(container).start();
        new Consumer(container).start();
    }
}
//producer
class Producer extends Thread{
    SynContainer container;
    public Producer(SynContainer container){
        this.container = container;
    }
    //production
    @Override
    public void run() {
        for (int i = 1; i < 100; i++) {
            container.push(new Chicken(i));
            System.out.println("Produced" + i + "Chicken");
            try {
                Thread.sleep(0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
//consumer
class Consumer extends Thread{
    SynContainer container;
    public Consumer(SynContainer container){
        this.container = container;
    }
    //consumption
    @Override
    public void run() {
        for (int i = 1; i < 100; i++) {
            System.out.println("Consumption-->" + container.pop().id + "Chicken");
            try {
                Thread.sleep(0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
//product
class Chicken{
    int id;
    public Chicken(int id) {
        this.id = id;
    }
}
//buffer
class SynContainer{
    //A container size is required
    Chicken[] chickens = new Chicken[10];
    //Container counter
    int count = 0;
    //The producer puts in the product
    public synchronized void push(Chicken chicken){
        //If the container is full, it needs to wait for consumers to consume
        if(count == chickens.length){
            //Inform consumers of consumption, production and waiting
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //If not, throw in the product
        chickens[count] = chicken;
        count++;
        //Consumers can be notified to consume products
        this.notifyAll();
    }

    //Consumer products
    public synchronized Chicken pop(){
        //Judge whether it can be consumed
        if (count == 0){
            //Waiting for producer production
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //If you can consume
        count--;
        Chicken chicken = chickens[count];
        //When finished, inform the producer to produce
        this.notifyAll();
        return chicken;
    }
}

Video link

8.2 solution 2

Concurrent collaboration model "producer / consumer model" -- > semaphore method

package thread.itc;
Testing: producer consumer model-->Signal lamp method
public class TestPC2 {
    public static void main(String[] args) {
        Program program = new Program();
        new Player(program).start();
        new Audience(program).start();
    }
}
//Producer -- > actor
class Player extends Thread{
    Program program;
    public Player(Program program){
        this.program = program;
    }
    @Override
    public void run() {
        for (int i = 1; i < 20; i++) {
            this.program.show ("Jay's Special session", i);
        }
    }
}
//Consumer -- > audience
class Audience extends Thread{
    Program program;
    public Audience(Program program){
        this.program = program;
    }
    @Override
    public void run() {
        for (int i = 1; i < 20; i++) {
            this.program.clap();
        }
    }
}
//Products -- > Programs
class Program{
    //The actors perform and the audience watch T
    //The audience applauded and the actor saluted F
    String name;//A performance
    int order;//Program serial number
    boolean  flag = true;//Signal lamp
    //perform
    public synchronized void show (String name, int order){
        if(!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("The actors performed" + name + "The first" + order + "Programs");
        //The audience applauded and the actors paid tribute
        this.notifyAll();
        this.name = name;
        this.order = order;
        this.flag = !this.flag;
    }
    //applause
    public synchronized void clap(){
        if (flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("The audience finished watching" + name + "The first" + order + "During the first program, warm applause broke out and the actors bowed");
        this.notifyAll();
        this.flag = !this.flag;
    }
}

Video link

9. Thread pool

* Background: resources that are often created and destroyed and used heavily, such as threads in concurrency, have a great impact on performance
* Idea: create many threads in advance and put them into the thread pool. When using, they can be obtained directly and put them back into the pool after use. It can avoid complex creation, destruction and reuse. Similar to public transport (bicycle) in life.
* Benefits:
	* Improved response time (reduced time to create new threads)
	* Reduce resource consumption (reuse threads in the thread pool instead of creating them every time)
	* Easy thread management

newFixedThreadPool: size of thread pool corePoolSize: size of core pool maximumPoolSize: maximum number of threads keepAliveTime: how long does the thread last when there is no task
API related to thread pool: ExecutorService and Executors void execute(Runnable command): execute tasks / commands without return value. It is generally used to execute runnable < T > Future < T > submit (callable < T > task): execute tasks with return value. It is generally used to execute Callablevoid shutdown(): close connection pool Executors: tool class and factory class of thread pool, Used to create and return different types of thread pools

package thread.syn;

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

//Test thread pool
public class TestPool {
    public static void main(String[] args) {
        //1. Create thread pool
        ExecutorService service = Executors.newFixedThreadPool(10);
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        //2. Close the connection
        service.shutdown();
    }
}

class MyThread implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + "  " + i);
        }
    }
}

Video link 1
Video link 2

Topics: Java Multithreading