Let the world no longer have difficult to understand multi-threaded!

Article Directory

1. Introduction to Threads

1. Common method calls and multithreading

2. Programs, Processes and Threads

  • 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.
  • A process is an execution process of a program, and it is a dynamic concept.Is the unit of system resource allocation.
  • Usually you can have several threads in a process, of course at least one thread in a process, otherwise it doesn't make sense.Threads are the units of CPU scheduling and execution.

3. Summary

(1) Threads are separate execution paths;
(2) When the program is running, there will be multiple threads in the background, such as the main thread and gc thread, even if there is no thread created by itself;
(3) main() is called the main thread and the entrance to the system 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 can not be interfered with artificially.
(5) For the same resource operation, there will be the problem of resource robbery, which requires concurrency control; threads will incur additional overhead, such as cpu scheduling time and concurrency control overhead.
(6) Each thread interacts in its own working memory, and improper memory control can result in inconsistent data.

2. How to Create Threads

1. Inherit Thread Class

(1) Steps

  • Customize a class to inherit the Thread class
  • Override the run() method to write a thread executor
  • Create a thread object and call the start() method to open the thread
public class ThreadTest1 extends Thread{

    @Override
    public void run() {
        for (int i = 0; i < 200; i++) {
            System.out.println("I'm writing code");
        }
    }

    public static void main(String[] args) {
        // Main Thread
        // Create Thread Object
        ThreadTest1 threadTest1 = new ThreadTest1();
        // Call the start method to open the thread
        threadTest1.start();
        //threadTest1.run(); //Execute run method first
        for (int i = 0; i < 1000; i++) {
            System.out.println("I am watching TV!");
        }
    }
}


When a thread is opened using the start() method, the program has two threads, run() and main(), and the running of the two threads is scheduled and executed by the CPU.

Note: The method to open a thread is the start() method, not the run() method.

(2) Implement multi-threaded synchronous download of pictures

Add Dependency

<dependency>
	<groupId>commons-io</groupId>
	<artifactId>commons-io</artifactId>
	<version>2.4</version>
</dependency>
public class ThreadTest2 extends Thread{

    // Address for downloading pictures
    private String url;
    // Saved file name
    private String name;

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

    @Override
    public void run() {
        WebDownload webDownload = new WebDownload();
        webDownload.downloader(url,name);
        System.out.println("The name of the download file is:" + name);
    }

    public static void main(String[] args) {
        ThreadTest2 t1 = new ThreadTest2("https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2941782042,3120113709&fm=26&gp=0.jpg","1.jpg");
        ThreadTest2 t2 = new ThreadTest2("https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1201576264,1254637397&fm=26&gp=0.jpg","2.jpg");
        ThreadTest2 t3 = new ThreadTest2("https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=4004355835,4118452948&fm=26&gp=0.jpg","3.jpg");
        t1.start();
        t2.start();
        t3.start();
    }
}

class WebDownload{
    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, download Method problem");
        }
    }
}


In this case, it can be explained that threads execute in parallel and alternately, and are scheduled by the CPU.

2. Implement Runnable Interface

(1) Steps

  • Customize a class to implement the Runnable interface
  • Implement the run() method and write the thread executor
  • Create an object for the Runnable implementation class, create a Thread object, and call the start () method
public class ThreadTest3 implements Runnable{

    public void run() {
        for (int i = 0; i < 200; i++) {
            System.out.println("I'm writing code");
        }
    }

    public static void main(String[] args) {
        // Main Thread
        // Create object of Runnable implementation class
        ThreadTest3 threadTest3 = new ThreadTest3();
        // Create a Thread object and call the start method
        new Thread(threadTest3).start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("I am watching TV!");
        }
    }
}

(2) Source Code Analysis



The Thread class already implements the Runnable interface, so we only need to create a thread object to call the start() method before opening a thread.
Instead, we implement the Runnable interface by creating a thread object before starting a thread, then creating a Thread object and calling the start() method with the thread object as a parameter to open the thread.

It is recommended to implement the Runnable interface, avoid the limitation of single inheritance, be flexible and convenient, and make it easy for the same object to be called by multiple threads.

(3) Implement multiple threads to call the same object

public class ThreadTest4 implements Runnable{

    // Current train ticket count
    private int ticketNums = 10;

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

    public static void main(String[] args) {
        ThreadTest4 ticket = new ThreadTest4();
        new Thread(ticket,"Zhang San").start();
        new Thread(ticket,"Li Si").start();
        new Thread(ticket,"King Five").start();
    }
}


The problem arises: Multiple threads operating on the same object can cause thread insecurity and data disorder.

(4) A case of tortoise-rabbit race

public class Race implements Runnable{

    private String winner;

    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(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // Determine if the match is finished
            boolean flag = gameOver(i);
            if (flag) {
                break;
            }
            System.out.println(Thread.currentThread().getName() + "Run" + i + "step");
        }

    }
    public boolean gameOver(int steps) {
        if (winner!=null) {
            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,"Tortoise").start();
        new Thread(race,"Rabbit").start();

    }
}

3. Implement Callable Interface

(1) Steps

To implement the Callable interface, a return value type is required
Override call() method
Create Target Object
Create Execution Service
Submit Execution
Get results
Shut down services

(2) Re-implement picture download

public class CallableTest implements Callable<Boolean> {
    // Address for downloading pictures
    private String url;
    // Saved file name
    private String name;

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

    public Boolean call() {
        WebDownload webDownload = new WebDownload();
        webDownload.downloader(url,name);
        System.out.println("The name of the download file is:" + name);
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CallableTest t1 = new CallableTest("https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2941782042,3120113709&fm=26&gp=0.jpg","1.jpg");
        CallableTest t2 = new CallableTest("https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1201576264,1254637397&fm=26&gp=0.jpg","2.jpg");
        CallableTest t3 = new CallableTest("https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=4004355835,4118452948&fm=26&gp=0.jpg","3.jpg");
        // Create Execution Service
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        // Submit Execution
        Future<Boolean> r1 = executorService.submit(t1);
        Future<Boolean> r2 = executorService.submit(t2);
        Future<Boolean> r3 = executorService.submit(t3);

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

        System.out.println(rs1);
        System.out.println(rs2);
        System.out.println(rs3);

        // Shut down services
        executorService.shutdown();
    }
}

3. Status of threads

1. Stop Threads

The stop(), destroy() methods provided by JDK are not recommended [obsolete]
A flag bit is recommended for terminating variables.

public class TestStop implements Runnable {
    // Define a flag bit
    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while (flag) {
            System.out.println("run...Thread-->" + i++);
        }
    }
    // Thread Stop Method
    public void stop(){
        flag = false;
        System.out.println("Thread stopped");
    }

    public static void main(String[] args) {
        TestStop testStop = new TestStop();
        // Open Thread
        new Thread(testStop).start();

        for (int i = 0; i <= 1000; i++) {
            System.out.println("current i Value of:" + i);
            if (i == 900) {
                testStop.stop();
            }
        }
    }
}

2. Thread Sleep

  • sleep (time) specifies the number of milliseconds the current thread is blocking;
  • The sleep has an exception InterruptedException;
  • The thread is ready when the sleep time reaches;
  • sleep can simulate network latency, countdown, etc.
  • Each object has a lock, and sleep does not release the lock.
public class TestSleep {
    public static void main(String[] args) {
        //Count down
        /*try {
            tenDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        // Get the time of the current system
        Date date = new Date();
        while (true) {
            try {
                Thread.sleep(1000);
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));
                date = new Date(System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    // Analog countdown
    public static void tenDown() throws InterruptedException {
        for (int i = 10; i > 0; i--) {
            Thread.sleep(1000);
            System.out.println("Count down:" + i + "s");
        }
    }
}


3. Thread Comfort

  • Causes the thread to pause, but not block, the currently executing thread
  • Change Thread from Running to Ready
  • Rescheduling the CPU will not necessarily succeed!See CPU mood
public class TestYield{

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

        new Thread(yield,"A").start();
        new Thread(yield,"B").start();
    }
}

class MyYield implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "Thread Starts Execution");
        // Thread Comfort
        Thread.yield();
        System.out.println(Thread.currentThread().getName() + "Thread Stops Execution");
    }
}

4. Thread Enforcement Join

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

public class TestJoin implements Runnable {
    @Override
    public void run() {
        for (int i = 1; i <= 1000; i++) {
            System.out.println("thread VIP Come on" + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new TestJoin());
        thread.start();
        // Main Thread
        for (int i = 1; i <= 500; i++) {
            if (i == 200) {
                thread.join();
            }
        System.out.println("main thread" + i);
    }
    }
}

5. Thread State Observation

  • NEW: Threads that have not been started are in this state.
  • RUNNABLE: The thread executing in the Java virtual machine is in this state.
  • BLOCKED: A blocked thread waiting for the monitor to lock is in this state.
  • WAITING: A thread that is waiting for another thread to perform a specific action is in this state.
  • TIED WAITING: A thread that is waiting for another thread to perform an action to reach the specified wait time is in this state.
  • TERMINATED: The exited thread is in this 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("////");
        });
        //NEW Status
        Thread.State state = thread.getState();
        System.out.println(state);

        thread.start();
        state = thread.getState();
        System.out.println(state);

        while (state != Thread.State.TERMINATED) {
            Thread.sleep(100);
            state = thread.getState();
            System.out.println(state);
        }
    }
}

6. Thread Priority

◆Java Provides a thread dispatcher to monitor all threads in the program that are ready after startup, and the thread dispatcher determines which thread should be dispatched to execute according to priority.
◆Thread priority is represented numerically with a range of 1~10.
    ◆Thread.MIN_PRIORITY=1;
    ◆Thread.MAX_PRIORITY=10;
    ◆Thread.NORMPRIORITY=5;
◆Change or get priority by
getPriority()      setPriority(int xxx)

public class TestPriority {
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName() + "--->" + Thread.currentThread().getPriority());
        //Set priority before starting thread
        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);

        t1.setPriority(5);
        t1.start();

        t2.setPriority(9);
        t2.start();

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

        t4.setPriority(3);
        t4.start();

        t5.setPriority(7);
        t5.start();

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

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


7. Daemon Threads

_Threads are divided into user and daemon threads
_Virtual machine must ensure user thread execution is complete
_Virtual machine does not have to wait for the daemon thread to finish executing
_For example, record operation logs in the background, monitor memory, garbage collection waiting.

public class TestDaemon {
    public static void main(String[] args) {
        God god = new God();
        Thread thread = new Thread(god);
        //Set as Daemon Thread
        thread.setDaemon(true);
        thread.start();
        new Thread(new You()).start();
    }
}
class You implements Runnable{
    @Override
        public void run() {
            for (int i = 1; i <= 365; i++) {
                System.out.println("Live happily every day" + i);
            }
    }
}
class God implements Runnable{
    @Override
    public void run() {
        while (true) {
            System.out.println("God protects you!");
        }
    }
}

4. Thread Synchronization

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

How to secure thread synchronization: Queue + Lock

_As multiple threads of the same process share the same storage space, which brings convenience and access conflict problems. To ensure the correctness of data access in the method, synchronized lock mechanism is added when accessing. When a thread acquires exclusive lock on an object and exclusive resources, other threads must wait and release the lock after use.The following problems exist:
_A thread holding a lock causes all other threads that need it to hang;
Locking and releasing locks can cause more context switching and scheduling delays and cause performance problems under multithreaded competition;
If a higher priority thread waits for a lower priority thread to release the lock, the priority will be inverted, causing performance problems.

1. Three major thread insecurity cases

Multiple objects operate on the same ticket

//Unsafe ticket-buying problem
public class UnsafeBuyTicket {
    public static void main(String[] args) {
        BuyTicket ticket = new BuyTicket();
        new Thread(ticket,"Xiao Zhang").start();
        new Thread(ticket,"petty thief").start();
        new Thread(ticket,"Xiaowang").start();
    }
}


class BuyTicket implements Runnable{

    //present quorum votes
    private int ticketNums = 10;
    //Define thread stop flag
    private boolean flag = true;

    @Override
    public void run() {
        while (flag) {
            try {
                buyTicket();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void buyTicket() throws InterruptedException {
        // Judge remaining votes
        if (ticketNums <= 0) {
            flag = false;
            return;
        }
        // Analog delay
        Thread.sleep(100);
        // Buy tickets
        System.out.println(Thread.currentThread().getName() + "-->Get the first" + ticketNums-- + "ticket");
    }
}


Bank withdrawal

public class UnsafeBank {
    public static void main(String[] args) {
        Account account = new Account(100,"Health Fund");
        Drawing you = new Drawing(account, 50, "You");
        Drawing yourFriend = new Drawing(account, 100, "yourFriend");

        you.start();
        yourFriend.start();

    }
}

//Account Class
class Account {
    //Account Balance
    int money;
    //Card number
    String name;

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

//Simulated withdrawal
class Drawing extends Thread {
    private Account account;
    //Money withdrawn
    private int drawingMoney;
    //Existing money
    private 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(Thread.currentThread().getName()+"Insufficient current balance");
            return;
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //Card Balance
        account.money = account.money - drawingMoney;
        //Existing money
        nowMoney = nowMoney + drawingMoney;

        System.out.println(account.name + "The balance is:" + account.money);
        System.out.println(this.getName() + "The money available is:" + nowMoney);
    }
}


Unsafe Collection

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

2. Thread synchronization methods and synchronization blocks

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

The synchronized method controls access to the Object. Each object corresponds to a lock, and 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 exclusive until the method returns, and then the blocked thread can acquire the lock and continue execution.

Defect: declaring a method synchronized will affect efficiency

_Synchronization block: synchronized (Obj) {}

_Obj calls it a synchronization monitor
_Obj can be any object, but shared resources are recommended as synchronization monitors
There is no need to specify a synchronization monitor in a synchronization method, because the synchronization monitor for a synchronization method is this, the object itself, or the class
_Synchronization monitor execution process
1. The first thread accesses, locks the synchronization monitor, and executes its code.
2. The second thread accessed and found that the synchronization monitor was locked and could not be accessed.
3. Once the first thread is accessed, unlock the synchronization monitor.
4. The second thread accesses, finds that the synchronization monitor has no lock, and then locks and accesses

Use synchronized synchronization method to solve the problem of unsafe ticket purchasing.


Use synchronized synchronized blocks to solve unsafe bank withdrawals.

Use synchronized synchronized blocks to solve collection insecurity problems


Test JUC security type collection

public class TestJUC {
    public static void main(String[] args) throws InterruptedException {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                list.add(Thread.currentThread().getName());
            }).start();
        }
        Thread.sleep(1000);
        System.out.println(list.size());
    }
}


Through source code analysis, the CopyOnWriteArrayList implements thread security internally through reentrant locks.

5. Deadlock

Multiple threads own some shared resources and wait for other threads to run, resulting in two or more threads waiting for each other to release resources and stopping execution.Deadlock may occur when a synchronization block has locks on more than two objects at the same time.

Case study: There is a lipstick and a mirror, Cinderella gets lipstick first, Snow White gets the mirror first, but then Cinderella wants Snow White's mirror, and Snow White wants Cinderella's lipstick, and each other is stiff, forming 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{

}
//Makeup
class Makeup extends Thread{
    //Require only one resource, use static to ensure only one resource
    static Lipstick lipstick = new Lipstick();
    static Mirror mirror = new Mirror();

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

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

    @Override
    public void run() {
        //Makeup
        try {
            makeup();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public void makeup() throws InterruptedException {
        if (choice == 0) {
            //Lock to get lipstick
            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 {
            //Get the lock on the mirror
            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.
2. Request and hold conditions: When a process is blocked by requesting resources, hold on to the resources it has acquired.
3. Non-deprivation conditions: Resources already acquired by a process cannot be forcibly deprived until they are exhausted.
4. Cyclic wait conditions: There is a head-to-tail cyclic wait resource relationship between processes.

The four prerequisites for deadlocks are listed above, and we can avoid deadlocks by breaking any one or more of them.

In this case, I can break the mutually exclusive condition to solve the deadlock problem

6. Lock

Starting with JDK5.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.
_Java.util.concurrent.Locks.LockInterfaces are tools that control 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.
_ReentrantLock class implements Lock. It has the same concurrency and memory semantics as synchronized. ReentrantLock is the most common thread-safe control, which can explicitly lock and release locks.

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{
    private int ticketNums = 10;
    //Explicitly define lock
    private final ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        while (true) {
            try{
                //Locking
                lock.lock();
                if (ticketNums > 0){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Get the first" + ticketNums-- + "Tickets");
                }else {
                    break;
                }
            }finally {
                //Unlock
                lock.unlock();
            }
        }
    }
}

Comparison of synchronized and Lock

_Lock is an explicit lock (manually open and close locks, don't forget to close locks) synchronized is an implicit lock, automatically released from scope.
_Lock only has code block locks, synchronized has code block locks and method locks.
With Lock locks, the JVM takes less time to schedule threads and performs better.And has better scalability (provides more subclasses)
_Priority:
_Lock > Synchronization Code Block (already in the method body, allocated resources) > Synchronization Method (outside the method body)

7. Thread Collaboration

1. Thread Communication

_Scenarios: Producer and Consumer Issues
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.
_If there is no product in the warehouse, the producer puts the product in the warehouse, otherwise stop production and wait until the product in the warehouse is removed by the consumer.
If there are products in the warehouse, the consumer can take the products away from consumption, otherwise stop the consumption and wait until the products are put in the warehouse again.

2. Thread Communication Problem Resolution

2.1 Pipeline Method

Concurrent Collaboration Model "Producer/Consumer Mode" - Process Approach
_Producer: Module responsible for production data (possibly method, object, thread, process);
_Consumer: Module responsible for processing data (possibly method, object, thread, process);
_Buffer: Consumers cannot use the producer's 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

public class TestPC {
    public static void main(String[] args) {
        Buffer buffer = new Buffer();
        new Producer(buffer).start();
        new Consumer(buffer).start();
    }

}
//Producer
class Producer extends Thread{
    Buffer buffer;
    public Producer(Buffer buffer) {
        this.buffer = buffer;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            buffer.push(new Chicken(i));
            System.out.println("Produced" + i + "Chicken");
        }
    }
}

//Consumer
class Consumer extends Thread {
    Buffer buffer;
    public Consumer(Buffer buffer) {
        this.buffer = buffer;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("Consumed" + buffer.pop().id + "Chicken");
        }
    }
}
//product
class Chicken{
    //Product Number
    int id;

    public Chicken(int id) {
        this.id = id;
    }
}
//Buffer
class Buffer{
    //Counter
    private int count = 0;
    //Store product
    Chicken[] chickens = new Chicken[10];

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

        }
        //Buffer empty, add product
        chickens[count] = chicken;
        count++;
        //Notify Consumers of Consumption
        this.notifyAll();
    }

    //Consumer Consumer Products
    public synchronized Chicken pop() {
        //Buffer empty, consumer waiting
        if (count == 0) {
            //Waiting for producer to produce
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //Buffer full, consumer products
        count--;
        Chicken chicken = chickens[count];
        //Notify producer of production
        this.notifyAll();
        return chicken;
    }
}

2.2 semaphore method

public class TestPC2 {
    public static void main(String[] args) {
        TV tv = new TV();
        new Player(tv).start();
        new Audience(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) {
                try {
                    this.tv.play("Playing at Happy Camp");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {
                try {
                    this.tv.play("Tremolo: Record the good life");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

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

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            try {
                tv.watch();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
//Products: Programs
class TV{
    //Performing Programs
    String show;
    //Define flags
    boolean flag = true;

    //perform
    public synchronized void play(String show) throws InterruptedException {
        if (!flag) {
            this.wait();
        }
        System.out.println("The actors performed" + show);
        //Notify viewers to watch
        this.notifyAll();
        this.show = show;
        this.flag = !this.flag;
    }
    //watch
    public synchronized void watch() throws InterruptedException {
        if (flag) {
            this.wait();
        }
        System.out.println("Watched" + show);
        //Inform an actor to perform
        this.notifyAll();
        this.flag = !this.flag;
    }
}

8. Thread Pool

_JDK5.0 provides thread pool correlation APl:ExecutorService And Executors
_ExecutorService: True thread pool interface.Common Subclass ThreadPoolExecutor
_void execute (Runnable command): Executes a task/command with no return value and is generally used to execute Runnable
< T > Future < T > submit (Callables < T > task): Executes a task, has a return value, and is generally used to execute Callable
_void shutdown(): Close connection pool
_Executors: Tool class, factory class for thread pools, used to create and return different types of thread pools

public class ThreadPool {
    public static void main(String[] args) {
        //Create Thread Pool
        ExecutorService service = Executors.newFixedThreadPool(10);

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

Tags: Java REST JDK network

Posted on Sun, 14 Jun 2020 21:16:15 -0400 by gidiag