Multithread Details

Catalog

Multithreaded

1 Overview

1.1 Tasks

1.2 Process

1.3 Multithreaded

2 Static Proxy

3 Lamda expression

4 Threads

4.1 Thread Creation

4.1.1 inherits the Thread class (emphasis)

4.1.2 Implementing Runnable Interface (Key)

4.1.3 Implement callable interface (Understanding)

4.2 Thread State

4.2.1 Stop Thread

4.2.2 Thread Hibernates

4.2.3 Thread yield

4.2.4 Thread Enforcement

4.2.5 Thread State Observation

4.3.6 Priority

4.3.7 Thread Daemon

5-Thread Synchronization

5.1 Queues and Locks

5.2 Synchronization Method and Synchronization Block

5.2.1 Supplement: Thread Security Collection CopyOnWriteArrayList

6 Deadlock

7 Lock

8 Producer and consumer issues

8.1 Pipeline Method

8.2 semaphore method

9 Thread Pool

Crazy Video: [Crazy Java] Multithreaded Details_ Bell-Bell-Bell_ bilibili

Multithreaded

1 Overview

1.1 Tasks

_There are too many examples of doing many things at the same time in reality. It seems that many tasks are being done at the same time. In fact, our brains still do only one thing at the same time.

1.2 Process

_Programs running in the operating system are processes, such as your QQ, player, game, IDE and so on.

_A process can have multiple threads, such as listening to sound, viewing images, watching marquees, etc. in a video at the same time

_1. When it comes to processes, you have to talk about procedures. A program is an ordered collection of instructions and data that has no meaning to run and is a static concept. _2. A process is an execution process of a program and it is a dynamic concept. Is the unit of system resource allocation_3. Usually a process can contain several threads, of course a process has at least one thread, otherwise it has no meaning. Threads are the units of CPU scheduling and execution.

Note: Many multithreads are simulated. True multithreading refers to having multiple CPUs, that is, multicores, such as servers. In the case of simulated multithreading, that is, in the case of a single cpu, the cpu can only execute one code at a time because the switch is fast, so there is an illusion of simultaneous execution.

Summary:1. Threads are independent execution paths; _2. When a program is running, there will be multiple threads in the background, such as the main thread and the gc thread, even if there is no thread created by itself. _3.main() is called the main thread, which is the entrance to the system and is used to execute the whole program. _4. In a process, if multiple threads are opened up, the running of threads is scheduled by a dispatcher (CPU), which is closely related to the operating system and cannot be interfered with artificially in sequence. _5. When operating on the same resource, there will be a problem of resource seizure, which requires concurrency control. _6. Threads incur additional overhead, such as CPU scheduling time and concurrency control overhead. _7. Each thread interacts in its own working memory, and improper memory control can cause data inconsistencies;

1.3 Multithreaded

Common method calls and multithreading

 

2 Static Proxy

 

package com.yw;

public class StaticProxy {
    public static void main(String[] args) {
        WeddingComapny weddingComapny=new WeddingComapny(new You());
        weddingComapny.HappyMarrt();
    }
}

interface Marry{
    void HappyMarrt();
}

//Real Role
class You implements Marry{

    @Override
    public void HappyMarrt() {
        System.out.println("Get married...");
    }
}

//delegable role
class WeddingComapny implements Marry{

    private Marry target;

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

    @Override
    public void HappyMarrt() {
        before();
        this.target.HappyMarrt();
        after();
    }

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

    private void before(){
        System.out.println("Before you get married, set up the scene");
    }
}

Result

Before you get married, set up the scene
 Get married...
Settlement

Static proxy summary:1. Both real objects and proxy objects need to implement the same interface_2. Proxy objects need to proxy real role benefits:Proxy objects can do many things that objects can't do_Real objects focus on doing their own things

3 Lamda expression

_The eleventh letter in the Greek alphabet, named Lambda in English to avoid overdefining internal classes_It is essentially a functional programming concept

(params) -> expression  [Expression]
(params) -> statement [Sentence]
(params) -> {statement }
123
new Thread(()-> System.out.println("Multithreaded Learning")).start();
1

Why use lambda expressions_1.Avoid overdefining your internal classes_2.Make your code look concise_3.Remove a lot of meaningless code, leaving only the core logic behind

Definition of a functional interface_1. Any interface that contains only one abstract method is a functional interface. _2. For a functional interface, we can create an object for that interface through a lambda expression.

General Writing

package com.yw;
//Derive lambda expression
public class TestLambda1 {
    //3 Static internal class
    static class Like2 implements ILike{

        @Override
        public void lambda() {
            System.out.println("i like lambda2");
        }
    }

    public static void main(String[] args) {
        ILike like=new Like();
        like.lambda();

        like=new Like2();
        like.lambda();

        //4 Local internal classes
        class Like3 implements ILike{

            @Override
            public void lambda() {
                System.out.println("i like lambda3");
            }
        }

        like=new Like3();
        like.lambda();

        //5 Anonymous internal class has no class name and must be supported by an interface or parent class
        like =new ILike() {
            @Override
            public void lambda() {
                System.out.println("i like lambda4");
            }
        };

        //6 lambda simplification
        like=()->{
            System.out.println("i like lambda5");
        };
        like.lambda();
    }
}

//1 interface
interface ILike{
    void lambda();
}

//Implementation Class
class Like implements ILike{

    @Override
    public void lambda() {
        System.out.println("i like lambda");
    }
}

To parameters

package com.yw;

public class TestLambda2 {

    public static void main(String[] args) {

        ILove love=(int a)->{
            System.out.println("i love you1-->"+a);
        };


        //Simplify 1 de-parameter type
        love=(a)->{
            System.out.println("i love you1-->"+a);
        };

        //Simplify 2 ()
        love=a -> {
            System.out.println("i love you1-->"+a);
        };

        //Simplify 3 
        //Summary: A lambda expression can be simplified to one line only if it has one line of code, and if it has more than one line, it is wrapped in a code block.
        //The precondition is that the interface is a functional interface
        love=a-> System.out.println("i love you1-->"+a);
        
        love.love(5);
    }

}

interface ILove{
    void love(int a);
}

class Love implements ILove{
    @Override
    public void love(int a) {
        System.out.println("i love you1-->"+a);
    }
}

4 Threads

4.1 Thread Creation

4.1.1 inherits the Thread class (emphasis)

package com.yw.demo01;

//Create threads by inheriting the Thread class
public class TestThead extends Thread{
    @Override
    public void run() {
        for (int i=0;i<20;i++){
            System.out.println("I'm looking at the code---"+i);
        }
    }

    public static void main(String[] args) {
        TestThead testThead=new TestThead();

        //Call the start() method to open the thread
        //testThead.start();

        testThead.run();

        for (int i=0;i<20;i++){
            System.out.println("I am learning multithreading---"+i);
        }
    }
}

Summary

Calling run() executes the run method first, synchronously

The start method is the default execution entry for the Thread class. When the start method is called, it means that the Thread starts execution and really implements multithreading.

Case Network Diagram Download

1 Import jar package commons-io-2.6,jar

 

package com.yw.demo01;

//Create threads by inheriting the Thread class
public class TestThead extends Thread{
    @Override
    public void run() {
        for (int i=0;i<20;i++){
            System.out.println("I'm looking at the code---"+i);
        }
    }

    public static void main(String[] args) {
        TestThead testThead=new TestThead();

        //Call the start() method to open the thread
        //testThead.start();

        testThead.run();

        for (int i=0;i<20;i++){
            System.out.println("I am learning multithreading---"+i);
        }
    }
}

 

4.1.2 Implementing Runnable Interface (Key)

package com.yw.demo01;

//Implement Runnable Interface
public class TestThread3 implements Runnable{
    @Override
    public void run() {
        for (int i=0;i<20;i++){
            System.out.println("I'm looking at the code---"+i);
        }
    }

    public static void main(String[] args) {
        TestThread3 testThead3=new TestThread3();

        //Create Thread Object
        Thread thread=new Thread(testThead3);

        //Call the start() method to open the thread
        thread.start();

        for (int i=0;i<20;i++){
            System.out.println("I am learning multithreading---"+i);
        }
    }
}

Summary

Recommended Use: Avoid single inheritance limitations, be flexible and convenient, and allow multiple threads to use the same object

case

package com.yw.demo01;
//Multiple threads operate on the same object
//Example of buying a train ticket
public class TestThread4 implements Runnable{

    private int titckNum=10;

    @Override
    public void run() {
        while (true){
            if (titckNum<=0){
                break;
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName()+"-->Get the first"+titckNum--+"Tickets");
        }

    }

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

        new Thread(ticket,"Xiao Ming").start();
        new Thread(ticket,"Teacher").start();
        new Thread(ticket,"Daniel").start();
    }
}

Result

Daniel-->Get the 10th ticket
 Teacher-->Got the ninth ticket
 Xiao Ming-->Get the eighth ticket
 Teacher-->Get the 7th ticket
 Xiao Ming-->Get the sixth ticket
 Daniel-->Get the 5th ticket
 Daniel-->Get the fourth ticket
 Xiao Ming-->Get the third ticket
 Teacher-->Get the second ticket
 Xiao Ming-->Get the first ticket
 Daniel-->Got ticket 0
 Teacher-->Get the first ticket

Case study: tortoise-rabbit race

package com.yw.demo01;

//Simulate tortoise-rabbit race
public class Race implements Runnable{

    //Winner
    private static String winner;

    @Override
    public void run() {
        for (int i = 0; i <=100 ; i++) {
            //Simulate rabbit rest
            if (Thread.currentThread().getName().equals("Rabbit") && i%10==0){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            boolean flag=gameOver(i);
            if (flag){
                break;
            }

            System.out.println(Thread.currentThread().getName()+"-->Run"+i+"step");
        }
    }

    //Determine if you have finished the game
    private boolean gameOver(int steps){
        if (winner!=null){
            //There is already a winner, the game is over
            return true;
        }
        if (steps>=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();
    }
}

Result

<span style="background-color:#f8f8f8"><span style="color:#333333 ">Rabbit-->0 Runs
 Rabbit-->1 run
 Rabbit-->2 runs
 Rabbit-->Run three runs
 Rabbit-->Run 4 Steps
 Rabbit-->5 runs
 Rabbit-->Run 6 Steps
 Rabbit-->Seven runs
 Rabbit-->8 runs
 Rabbit-->9 runs
 Tortoise-->Run 0 steps
 Tortoise-->1 run
 Tortoise-->2 runs
 Tortoise-->Run three runs
 Tortoise-->Run 4 Steps
 Tortoise-->5 runs
 Tortoise-->Run 6 Steps
 Tortoise-->Seven runs
 Tortoise-->8 runs
 Tortoise-->9 runs
 Tortoise-->10 runs
 Tortoise-->11 runs
 Tortoise-->12 runs
 Tortoise-->13 runs
 Tortoise-->14 runs
 Tortoise-->15 runs
 Tortoise-->16 runs
 Tortoise-->17 runs
 Tortoise-->18 runs
 Tortoise-->19 runs
 Tortoise-->20 runs
 Tortoise-->Running 21 steps
 Tortoise-->22 runs
 Tortoise-->23 runs
 Tortoise-->24 runs
 Tortoise-->25 runs
 Tortoise-->26 runs
 Tortoise-->27 runs
 Tortoise-->28 runs
 Tortoise-->29 runs
 Tortoise-->Run 30 steps
 Tortoise-->Run 31 steps
 Tortoise-->Run 32 steps
 Tortoise-->Run 33 steps
 Tortoise-->Run 34 steps
 Tortoise-->Run 35 steps
 Tortoise-->Run 36 steps
 Tortoise-->37 runs
 Tortoise-->Run 38 steps
 Tortoise-->Run 39 steps
 Tortoise-->Run 40 steps
 Tortoise-->Run 41 steps
 Tortoise-->Run 42 steps
 Tortoise-->Run 43 steps
 Tortoise-->Run 44 steps
 Tortoise-->Run 45 steps
 Tortoise-->46 runs
 Tortoise-->47 runs
 Tortoise-->Run 48 steps
 Tortoise-->Run 49 steps
 Tortoise-->50 runs
 Tortoise-->51 runs
 Tortoise-->52 runs
 Tortoise-->53 runs
 Tortoise-->54 runs
 Tortoise-->55 runs
 Tortoise-->56 runs
 Tortoise-->57 runs
 Tortoise-->58 runs
 Tortoise-->59 runs
 Tortoise-->Running 60 steps
 Tortoise-->Run 61 steps
 Tortoise-->Running 62 steps
 Tortoise-->Run 63 steps
 Tortoise-->Run 64 steps
 Tortoise-->Running 65 steps
 Tortoise-->Running 66 steps
 Tortoise-->67 runs
 Tortoise-->68 runs
 Tortoise-->Running 69 steps
 Tortoise-->70 runs
 Tortoise-->71 runs
 Tortoise-->72 runs
 Tortoise-->73 runs
 Tortoise-->74 runs
 Tortoise-->75 runs
 Tortoise-->76 runs
 Tortoise-->77 runs
 Tortoise-->78 runs
 Tortoise-->79 runs
 Tortoise-->Running 80 steps
 Tortoise-->Run 81 steps
 Tortoise-->82 runs
 Tortoise-->83 runs
 Tortoise-->84 runs
 Tortoise-->Running 85 steps
 Tortoise-->86 runs
 Tortoise-->87 runs
 Tortoise-->88 runs
 Tortoise-->89 runs
 Tortoise-->Running 90 steps
 Tortoise-->91 runs
 Tortoise-->92 runs
 Tortoise-->93 runs
 Tortoise-->94 runs
 Tortoise-->95 runs
 Tortoise-->96 runs
 Tortoise-->97 runs
 Tortoise-->98 runs
 Tortoise-->99 runs
winner is Tortoise</span></span>

4.1.3 Implement callable interface (Understanding)

  1. To implement the callable interface, a return value type is required

  2. Override call method, need to throw exception

  3. Create Target Object

  4. Create an execution service: ExecutorService ser=Executors.newFixedThreadPool(1);

  5. Commit execution: Future<Boolean>result1=ser.submit(1);

  6. Get the result: boolean r1=result1.get();

  7. Shut down service: ser,shutdowmNow();

package com.yw.demo02;

import com.yw.demo01.TestThread2;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;

//Implement Callable
public class TestCallable implements Callable {
    private String url; //Web Picture Address
    private String name;//Saved file name

    public TestCallable(String url,String name){
        this.url=url;
        this.name=name;
    }

    @Override
    public Object call() throws Exception {
        WebDownLoader webDownLoader=new WebDownLoader();
        webDownLoader.downloader(url,name);
        System.out.println("Downloaded file name:"+name);
        return true;
    }

    //Downloader
    class WebDownLoader{
        //Download Method
        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 Exceptions, downloader Method problem");
            }
        }

    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestCallable t1=new TestCallable("https://img-pre.ivsky.com/img/tupian/pre/202104/13/maomi_youzai-002.jpg","1.jpg");
        TestCallable t2=new TestCallable("https://img-pre.ivsky.com/img/tupian/pre/202104/13/maomi_youzai-002.jpg","2.jpg");
        TestCallable t3=new TestCallable("https://img-pre.ivsky.com/img/tupian/pre/202104/13/maomi_youzai-002.jpg","3.jpg");

        //Create Execution Service
        ExecutorService ser= Executors.newFixedThreadPool(3);

        //Submit Execution
        Future<Boolean> r1=ser.submit(t1);
        Future<Boolean> r2=ser.submit(t2);
        Future<Boolean> r3=ser.submit(t3);

        //Get results
        Boolean rs1 = r1.get();
        Boolean rs2 = r2.get();
        Boolean rs3 = r3.get();

        //Shut down services
        ser.shutdownNow();

    }
}

Result

<span style="background-color:#f8f8f8"><span style="color:#333333 "> Downloaded file name: 1.jpg
 Downloaded file named:3.jpg
 Downloaded file named:2.jpg</span></span>

Summary:

Return values can be defined

Exceptions can be thrown

4.2 Thread State

Five States

 

 

 

4.2.1 Stop Thread

  • stop(), destroy() methods are not recommended

  • Recommend that the thread stop itself

  • It is recommended that you use a flag bit to terminate the variable and terminate the thread when flag=false.

package com.yw.state;

/**
 * - stop(), destroy() methods are not recommended
 *
 * - Recommend that the thread stop itself
 *
 * - It is recommended that you use a flag bit to terminate the variable and terminate the thread when flag=false.
 */
public class TestStop implements Runnable{

    private boolean flag=true;

    @Override
    public void run() {
        int i=0;
        while (flag){
            System.out.println("run....Thread"+i++);
        }

    }

    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("Thread stopped");
            }
        }
    }
}

4.2.2 Thread Hibernates

  • Sleep (time) specifies the number of milliseconds the current thread is blocking 1000ms=1s

  • The sleep has an exception InterruptedException;

  • Thread is ready when sleep time arrives

  • sllep can simulate network latency, countdown, etc.

  • Every object has a lock, sleep does not release the lock

package com.yw.state;

import java.text.SimpleDateFormat;
import java.util.Date;

//Analog countdown
public class TestSleep2{

    public static void main(String[] args) {
//        try {
//            tenDown();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

        //Print the current system time
        Date startTime=new Date(System.currentTimeMillis());

        while (true){
            try {
                Thread.sleep(1000);
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
                startTime=new Date(System.currentTimeMillis());//Update current time
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    //Analog countdown
    public static void tenDown () throws InterruptedException{
        int num=10;
        while (true){
            Thread.sleep(1000);
            System.out.println(num--);
            if (num<=0){
                break;
            }
        }

    }

}

4.2.3 Thread yield

  • Causes the thread to pause, but not block, the currently executing thread

  • Change Thread from Running to Ready

  • Let cpu reschedule, comity may not succeed, see cpu mood

package com.yw.state;

public class TestYield {

    public static void main(String[] args) {
        MyYield myYield=new MyYield();

        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() + "Thread Stops Execution");
    }

}

4.2.4 Thread Enforcement

  • Join merges threads and waits until this thread finishes before executing other threads, which are blocked

  • Imagine jumping in the queue

package com.yw.state;

public class TestJoin implements Runnable{

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

        for (int i = 0; i <1000 ; i++) {
            if (i==200){
                thread.join();//Queue Break
            }
            System.out.println("main"+i);
        }
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("thread vip Coming"+i);

        }
    }
}

4.2.5 Thread State Observation

public static enum Thread.State

Thread state, Threads can be in one of the following states: NEW_not yet started thread is in this state RUNNABLE_executed thread in Java virtual machine is in this state BLOCKED_blocked thread waiting for monitor lock is in this state WAITING_waiting for another thread to perform a specific action TIMED WAITING_waiting for another thread in this state Threads whose process execution action reaches the specified wait time are in this state TERMINATED_Exited threads are in this state

_A thread can be in a state at a given point in time, which does not reflect the virtual machine state of any operating system thread state.

package com.yw.state;
//Observing test 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("/");
            }
        });

        //Observed state
        Thread.State state=thread.getState();
        System.out.println(state);

        //After observation starts
        thread.start();
        state=thread.getState();
        System.out.println(state);


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

output

<span style="background-color:#f8f8f8"><span style="color:#333333">NEW
RUNNABLE
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
/
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
/
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
/
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
/
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
/
TERMINATED
​
Process finished with <span style="color:#770088">exit</span> code <span style="color:#116644">0</span>
​</span></span>

4.3.6 Priority

  • Java provides a thread dispatcher to monitor all threads that are ready after startup in the program. Thread dispatcher installation priority determines which thread should be dispatched to execute.

  • Thread priority is represented numerically and ranges from 1 to 10 Thread.MIN_PRIORITY = 1; Thread.MAX_PRIORITY = 10; _Thread.NOPM_PRIORITY = 5;

Change or get priority_getPriority() setPriority(int xx) by

package com.yw.state;

//Test Priority
public class TestPriority{
    public static void main(String[] args) {
        //Main Thread Default Priority
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());

        MyPriority myPriority=new MyPriority();

        Thread t1 = new Thread(myPriority);
        Thread t2 = new Thread(myPriority);
        Thread t3 = new Thread(myPriority);
        Thread t4 = new Thread(myPriority);
        Thread t5 = new Thread(myPriority);
        Thread t6 = new Thread(myPriority);

        //Set priority first, at startup
        t1.start();

        t2.setPriority(1);
        t2.start();

        t3.setPriority(4);
        t3.start();

        t4.setPriority(Thread.MAX_PRIORITY);
        t4.start();

        t5.setPriority(8);
        t5.start();

        t6.setPriority(7);
        t6.start();
    }

}

class MyPriority implements Runnable{


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

Result

<span style="background-color:#f8f8f8"><span style="color:#333333">main-->5
Thread-3-->10
Thread-4-->8
Thread-5-->7
Thread-0-->5
Thread-2-->4
Thread-1-->1
​
Process finished with <span style="color:#770088">exit</span> code <span style="color:#116644">0</span>
​</span></span>

4.3.7 Thread Daemon

  • Threads are divided into user threads and daemon threads

  • Virtual machines must ensure that user threads are executed

  • The virtual machine does not have to wait for the daemon thread to finish executing

  • For example: background record operation log, monitor memory, garbage collection and so on...

package com.yw.state;

public class TestDaemon {
    public static void main(String[] args) {
        God god=new God();
        You you=new You();

        Thread thread=new Thread(god);
        thread.setDaemon(true); //The default false indicates a user process, and normal threads are user threads


        thread.start();//Daemon thread startup

        new Thread(you).start();//User Thread Start


    }


}
//lord
class God implements Runnable{
    @Override
    public void run() {
        while (true){
            System.out.println("----God-----");
        }
    }
}


//you
class You implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i <36500 ; i++) {
            System.out.println("Alive"+i+"day");
        }
        System.out.println("#########bye##########");
    }
}

5-Thread Synchronization

Multiple threads operate on the same resource

Concurrency: The same object is operated on simultaneously by multiple threads

_In real life, we will encounter the problem of "the same resource, many people want to use". For example: the canteen queues for dinner, everyone wants to eat, the most natural solution is to queue. One by one

When dealing with multithreading problems, multiple threads access the same object (concurrently) and some threads want to modify it. Thread synchronization is a mechanism in which multiple threads that need to access this object at the same time enter the waiting pool of this object to form a queue, waiting for the previous thread to finish using it, and the next thread to use it again.

5.1 Queues and Locks

_Because multiple threads of the same process share the same storage space, which brings convenience and access conflicts. In order to ensure the correctness of data access in the method, synchronized lock mechanism is added when accessing. When a thread acquires exclusive locks on objects and exclusive resources, other threads must wait and release the locks after use. There are the following problems:1. A thread with a lock can cause other threads needing the lock to hang; _2. Under multithreaded competition, unlocking and releasing locks can cause more context switching and scheduling delays, causing performance problems; _3. If a higher priority thread waits for a lower priority thread to release the lock, the priority will be inverted, causing performance problems.

Thread Insecurity Case 1: Insecure Buying

package com.yw.syn;

public class UnsafeBuyTicket {
    public static void main(String[] args) {
        BuyTicket buyTicket=new BuyTicket();

        new Thread(buyTicket,"a").start();
        new Thread(buyTicket,"b").start();
        new Thread(buyTicket,"c").start();

    }
}

class BuyTicket implements Runnable{

    private int ticketNumm=10;
    boolean flag=true;

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

    private void buy(){
        if (ticketNumm<=0){
            flag=false;
            return;
        }

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

        //Buy tickets
        System.out.println(Thread.currentThread().getName()+"Get it"+ticketNumm--);
    }
}

Result

<span style="background-color:#f8f8f8"><span style="color:#333333 ">c gets 10
b Get 9
a Get 8
a Get 7
b Get 6
c Get 5
a Get 4
c Get 3
b Get 3
c Get 2
b Get 1
a Get 0
c Get it-1
​</span></span>

Result appears -1

Thread insecurity case 2: Bank withdrawal

package com.yw.syn;

public class UnsafeBank {
    public static void main(String[] args) {
        Account account=new Account(100,"Travel Fund");

        Drawing you=new Drawing(account,50,"you");
        Drawing xiaoming=new Drawing(account,100,"xiaoming");

        you.start();
        xiaoming.start();

    }
}

//account
class Account{
    int money;
    String name;

    public Account(int money, String name) {
        this.money = money;
        this.name = name;
    }
}

//Bank: Simulated withdrawal
class Drawing extends Thread{
    Account account;//account
    //How much money has been withdrawn
    int drawingMoney;
    //How much money do you have now
    int noeMoney;

    public Drawing(Account account,int drawingMoney,String name){
        super();
        this.account=account;
        this.drawingMoney=drawingMoney;
    }

    @Override
    public void run() {
        if (account.money-drawingMoney<0){
            System.out.println(Thread.currentThread().getName()+"Not enough money to take");
            return;
        }

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

        //Card Balance = Balance = Money you withdraw
        account.money=account.money-drawingMoney;
        //Money in your hand
        noeMoney=noeMoney+drawingMoney;

        System.out.println(account.name+"The balance is:"+account.money);
        System.out.println(this.getName()+"Money in your hand:"+noeMoney);

    }
}

Result

The balance of the travel fund is:50
Thread-0 Money in hand: 50
 The balance of the travel fund is:-50
Thread-1 Money in hand: 100

Thread Insecurity Case 3: Collection

package com.yw.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 < 10000; i++) {
            new Thread(()->{
                list.add(Thread.currentThread().getName());
            }).start();
        }
        System.out.println(list.size());
    }
}

5.2 Synchronization Method and Synchronization Block

Since we can use the private keyword to ensure that data objects can only be accessed by methods, we only need to propose a mechanism for methods, which is the synchronized keyword, which includes two uses: the synchronized method and the synchronized block.

Synchronization method: public synchronized void method(int args){}

_Synchronized methods control access to "objects". Each object corresponds to a lock. Each synchronized method must acquire a lock on the object calling the method to execute. Otherwise, the thread will block. Once the method executes, the lock will be exclusively released until the method returns. Then the blocked thread can acquire the lock and continue execution.

Defect: Declaring a large method as synchronized will affect efficiency.

_The contents that need to be modified in the method need to be locked. Too many locks waste resources.

Synchronization block: synchronized (obj){ }

_obj calls it a synchronization monitor_obj can be any object, but it is recommended that a shared resource be used as a synchronization monitor synchronization method without specifying a synchronization monitor, because the synchronization monitor for a synchronization method is this, is the object itself, or is a class

For example, modify thread insecurity case 1: Buy ticket (synchronization method)

private synchronized void buy(){ //Lock is this
        if (ticketNumm<=0){
            flag=false;
            return;
        }

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

        //Buy tickets
        System.out.println(Thread.currentThread().getName()+"Get it"+ticketNumm--);
    }

Synchronization block

Modify Thread Insecurity Case 2: Draw Money

 @Override
    public void run() {
        synchronized (account){
            if (account.money-drawingMoney<0){
                System.out.println(Thread.currentThread().getName()+"Not enough money to take");
                return;
            }

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

            //Card Balance = Balance = Money you withdraw
            account.money=account.money-drawingMoney;
            //Money in your hand
            noeMoney=noeMoney+drawingMoney;

            System.out.println(account.name+"The balance is:"+account.money);
            System.out.println(this.getName()+"Money in your hand:"+noeMoney);
        }
    

    }

Modify Thread Insecurity Case 3: Collection

public class UnsafeList {
    public static void main(String[] args) {
        List<String> list=new ArrayList<String>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                synchronized (list){
                    list.add(Thread.currentThread().getName());
                }

            }).start();
        }
        System.out.println(list.size());
    }
}

Synchronization Monitor Execution Procedure_1.First Thread Access, Lock Synchronization Monitor, Execute Code_2.Second Thread Access, Discover Synchronization Monitor, Can't Access_3.First Thread Access Completed, Unlock Synchronization Monitor_4.Second Thread Access, Discover Synchronization Monitor Not Locked, Lock and Access

The object of the lock is the amount of change that needs to be added or deleted

5.2.1 Supplement: Thread Security Collection CopyOnWriteArrayList

Understand first

//Collection of test thread 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(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(list.size());
    }

}

6 Deadlock

  • Threads hug the resources needed by the object and then become stuck.

  • Deadlock can occur when two or more threads are waiting for each other to release resources and execution stops. A synchronization block has locks on more than two objects at the same time.

Cases like two people putting on make-up and mirror lipstick

package com.yw.deadlock;
//Deadlock: Multiple threads hold each other's needed resources and then become deadlocked
public class DeadLock {
    public static void main(String[] args) {
        Makeup g1=new Makeup(0,"Grilla australis");
        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, and only one is guaranteed with static
    static Lipstick lipstick=new Lipstick();
    static Mirror mirror=new Mirror();

    int choice;//Choice
    String girlName; //People who use cosmetics

    Makeup(int choice,String girlName){
        this.choice=choice;
        this.girlName=girlName;
    }


    @Override
    public void run() {
        super.run();
    }

    //Makeup, holding each other's locks, is to get the other's resources
    private void makeup() throws InterruptedException {
        if (choice==0){
            synchronized (lipstick){
                System.out.println(this.girlName+"Lock to get lipstick");
                Thread.sleep(1000);

                synchronized (mirror){
                    System.out.println(this.girlName+"Get the lock on the mirror");
                }
            }
        }else{
            synchronized (mirror){
                System.out.println(this.girlName+"Get the lock on the mirror");
                Thread.sleep(2000);

                synchronized (lipstick){
                    System.out.println(this.girlName+"Lock to get lipstick");
                }
            }
        }

    }
}

As a result,

Gray Palm gets the lock for lipstick

Snow White gets the lock on the mirror

Make each other wait for the other to release resources

Solve

  //Makeup, holding each other's locks, is to get the other's resources
    private void makeup() throws InterruptedException {
        if (choice==0){
            synchronized (lipstick){
                System.out.println(this.girlName+"Lock to get lipstick");
                Thread.sleep(1000);             
            }
             synchronized (mirror){
                    System.out.println(this.girlName+"Get the lock on the mirror");
                }
        }else{
            synchronized (mirror){
                System.out.println(this.girlName+"Get the lock on the mirror");
                Thread.sleep(2000);
             
            }
             synchronized (lipstick){
                    System.out.println(this.girlName+"Lock to get lipstick");
                }
        }

    }

Four prerequisites for deadlock generation:1. Mutual exclusion: A resource can only be used by one process at a time. Request and Hold Conditions: A process is blocked by requests for resources and remains open to acquired resources. _3. Non-deprivation conditions: Resources already acquired by a process cannot be forcibly deprived until they have been used up. _4. Cyclic wait conditions: A head-to-tail cyclic wait resource relationship is formed between several processes.

7 Lock

Re-lockable

  1. Starting with JDK 5.0, Java provides a more powerful thread synchronization mechanism -- synchronization is achieved by explicitly defining synchronization lock objects. Synchronization locks use Lock objects to act as

  2. The java.util.concurrent.locks.Lock interface is a tool that controls access to shared resources by multiple threads. Locks provide exclusive access to shared resources. Only one thread can lock Lock objects at a time. A thread should obtain Lock objects before it starts accessing shared resources.

  3. The ReentrantLock class implements Lock, which has the same concurrency and memory semantics as synchronized. ReentrantLock is commonly used in thread-safe control to explicitly lock and release locks.

Lock lock case

package com.yw.goji;

import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
    public static void main(String[] args) {
        TestLock2 testLock2=new TestLock2();

        new Thread(testLock2).start();
        new Thread(testLock2).start();
        new Thread(testLock2).start();
    }
}

class  TestLock2 implements Runnable{

    int ticketNum=10;

    //Define lock
    private final ReentrantLock lock=new ReentrantLock();

    @Override
    public void run() {
        while (true){
                try {
                    lock.lock();//Locking
                    if (ticketNum>0) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(ticketNum--);
                    }else{
                        break;
                    }
                }finally {
                    lock.unlock();//Unlock
                }
        }
    }
}

Synchronized versus Lock_1.Lock is an explicit lock (manually open and close lock, don't forget to close lock) Synchronized is an implicit lock that automatically releases the scope_2.Lock only has code block locks, synchronized has code block locks and method locks_3.With Lock locks, the JVM will spend less time dispatching threads and perform better. (Provides more subclasses)4. Priority order: Lock > Synchronization code block (already in the method body, allocating appropriate resources) > Synchronization method (outside the method body)

8 Producer and consumer issues

  1. Assuming that only one product can be stored in a warehouse, the producer puts the product into the warehouse, and the consumer takes the product out of the warehouse for consumption.

  2. If there is no product in the warehouse, the producer puts the product in the warehouse, otherwise stops production and waits until the product in the warehouse is removed by the consumer.

  3. If there are products in the warehouse, the consumer can take the product away from consumption, otherwise stop consumption and wait until the warehouse puts the product again.

     

This is a thread synchronization problem where producers and consumers share the same resource and are dependent and conditional on each other.

  1. For producers, consumers should be notified to wait before they produce a product, and consumers should be notified to consume immediately after they produce a product.

  2. For consumers, after consumption, to notify producers that consumption has ended, new products need to be produced for consumption.

  3. In the producer-consumer problem, synchronized is not enough_synchronized to prevent concurrent updates to the same shared resource, synchronized_synchronized cannot be used to achieve message delivery (communication) between different threads

Java provides several ways to solve communication problems between threads

Note: Both methods of the Object class can only be used in synchronization methods or synchronization code blocks, otherwise lllegalMonitorStateException will be thrown

Solution 1: Concurrent Collaboration Model "Producer/Consumer Mode" - >Pipeline Method_1. Producer: Module responsible for production data (possibly method, object, thread, process); _2. Consumer: Module responsible for processing data (possibly method, object, thread, process); Buffer: Consumers cannot use producer data directly, there is a "buffer" between them

The producer puts the produced data in the buffer and the consumer pulls the data out of the buffer

8.1 Pipeline Method

package com.yw.goji;

//Producer/Consumer Model"- >Procedure Law
//Producer Consumer Product Buffer
public class TestPC {
    public static void main(String[] args) {
        SynContainer container=new SynContainer();
        Productor productor=new Productor(container);
        Comsumer comsumer=new Comsumer(container);

        productor.start();
        comsumer.start();

    }
}


//Producer
class Productor extends Thread{
    SynContainer container;

    public Productor(SynContainer container){
        this.container=container;
    }

    //production
    @Override
    public void run() {
        for (int i = 0; i <100 ; i++) {
            container.push(new Chicken(i));
            System.out.println("Produced"+i+"Chicken");
        }
    }
}

//Consumer
class Comsumer extends Thread{
    SynContainer container;

    public Comsumer(SynContainer container){
        this.container=container;
    }

    //consumption
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("Consumed-->"+container.pop().id+"Chicken");
        }
    }
}

//product
class Chicken{
    int id;//Product Number

    public Chicken(int id) {
        this.id = id;
    }
}

//Buffer
class SynContainer{
    //Container size
    Chicken[] chickens=new Chicken[10];
    //Container Counter
    int count=0;

    //Producer put in product
    public synchronized void push(Chicken chicken){
        if (count==chickens.length){
            //Notify consumers of consumption, producers wait
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //If it's not full, we need to throw it in
        chickens[count]=chicken;
        count++;

        //Consumers can be notified of their consumption
        this.notifyAll();
    }

    //Consumers put in products
    public synchronized Chicken pop(){
        //Judging whether to consume
        if (count==0){
            //Waiting for producers to produce, consumers to wait
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //If consumable
        count--;
        Chicken chicken=chickens[count];

        //Consumption is over, notify producer of production
        this.notifyAll();

        return chicken;
    }
}

Solution 2:

Concurrent Collaboration Model "Producer/Consumer Mode" - > Semaphore Method

8.2 semaphore method

package com.yw.goji;

//Producer/Consumer Mode"- > Signal Light Method, Signpost Resolution
public class TestPC2 {
    public static void main(String[] args) {
        TV tv=new TV();
        new PLayer(tv).start();
        new Watcher(tv).start();
    }

}

//Producer--Actor
class PLayer extends Thread{
    TV tv;
    public PLayer(TV tv){
        this.tv=tv;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            if (i%2==0){
                this.tv.play("Happy Camp");
            }else {
                this.tv.play("Tremolo: Record the good life");
            }
        }
    }
}


//Consumer--"Audience
class Watcher extends Thread{
    TV tv;
    public Watcher(TV tv){
        this.tv=tv;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            this.tv.watch();
        }
    }
}

//Product--"Program
class TV{
    //Performers perform, audiences wait
    //Audience watching, actor waiting
    String voice;//Performing Programs
    boolean flag=true;

    //perform
    public synchronized void play(String voice){
        if (!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("The actors performed:"+voice);
        //Notify viewers to watch
        this.voice=voice;
        //Notification Wake-up
        this.notifyAll();

        this.flag=!this.flag;
    }

    //watch
    public synchronized void watch(){


        if (flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("Watched:"+voice);
        //Inform an actor to perform
        this.notifyAll();
    }
}

9 Thread Pool

Background: Often created and destroyed resources that are particularly heavily utilized, such as threads in concurrent situations, can have a significant impact on performance.

Idea: Create many threads in advance, put them in the thread pool, get them directly when using, and put them back into the pool when using them. Frequent creation of destruction and reuse can be avoided. Similar to public transportation in life.

Benefits: 1. Increase response speed (reduce the time to create new threads)2. Reduce resource consumption (reuse threads in the thread pool, do not need to be created every time)3. Easy thread management (...) corePoolSize: Core pool size_maximumPoolSize: Maximum threads

JDK 5.0 has provided thread pool related API s:_ExecutorService and Executors ExecutorService: true thread pool interface. Common subclasses ThreadPoolExecutor_void execute(Runnable cgmmand): perform tasks/commands with no return value and are generally used to execute Runnable_Future submit (Callable) : Execute tasks, have return values, and generally perform Callable_void shutdown(): Close connection pools_Executors:Tool classes, Thread pools'factory classes, which are used to create and return different types of thread pools

package com.yw.goji;


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

//Test Thread Pool
public class TestPool {
    public static void main(String[] args) {
        //1 Create a thread pool
        //The newFixedThreadPool parameter is: Thread pool size
        ExecutorService service= Executors.newFixedThreadPool(10);

        //implement
        service.execute(new MyThread()); service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());

        //Close Connection
        service.shutdown();
    }
}

class MyThread implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

Keywords: Java Back-end thread

Added by jkkenzie on Fri, 05 Nov 2021 18:22:14 +0200