Java multithreading [LeetCode]

LeetCode antithesis

1114. Print in sequence

Source: LeetCode link: leetcode-cn.com/problems/pr… Copyright belongs to the Collar buckle network. Commercial reprint please contact official authorization, non-commercial reprint please indicate the source.

The title

We provide a class:

public class Foo {
  public void one(a) { print("one"); }
  public void two(a) { print("two"); }
  public void three(a) { print("three"); }}Copy the code

Three different threads will share an instance of Foo.

  • Thread A will call the one() method
  • Thread B will call the two() method
  • Thread C will call the three() method
  • Design modifications to ensure that the two() method is executed after the one() method and the three() method after the two() method.

Antithesis thought

First time to see the topic of multithreading, a little interesting

In fact, the problem is also very simple, is to make multithreaded procedures in order to output, just learned the high concurrency programming, start to try

  1. Simulate a simple product productionChain environment, provide a productionChain stack (or queue) as raw material warehouse (simple warehouse stacking items, the first stack of things to find a long time to take out HHH), used to store raw materials, incidentally initialization pay a rent what
    private Stack<Integer> productionChain ;
    public Foo(a) {
        // Init Resources Pool
        productionChain = new Stack<>();
    }
    Copy the code
  2. Then calculate what raw materials need first, what kind of dependence exists between raw materials
    Three methods need to be called, the latter two depending on the first two respectively
    // There are dependencies: 1 -> 2 -> 3
    // Two raw material ids are given here. If there are more dependent conditions, more should be considered
    private final int pidOfFirst = 1;
    private final int pidOfSecond = 2;
    // At the same time, a resource lock is required, which can be used as a limited production equipment in a production plant. Only one raw material can be produced or processed at the same time
    private final Object resLock = new Object();
    Copy the code
  3. Production line design
    // The following three production lines are set up in the first-second-third order
    public void first(Runnable printFirst) throws InterruptedException {
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
    }
    public void second(Runnable printSecond) throws InterruptedException {
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
    }
    public void third(Runnable printThird) throws InterruptedException {
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
    }
    Copy the code
  4. Raw material distribution and product processing
  • Raw material 1 production
    public void first(Runnable printFirst) throws InterruptedException {
        // Deliver the tool to the manufacturer for production
        synchronized (resLock){
            // Make the product
            productionChain.push(pidOfFirst);
            // printFirst.run() outputs "first". Do not change or remove this line.
            printFirst.run();
            // When production is completed, inform other processes to start workresLock.notifyAll(); }}Copy the code
  • Raw material 2 production
    public void second(Runnable printSecond) throws InterruptedException {
        // Deliver the tool to the manufacturer for production
        synchronized (resLock){
            // You need to check whether the resource pool has the required raw materials
            while( productionChain.empty() || productionChain.peek() ! = pidOfFirst ){// It is useless to get tools without raw materials, just wait for raw material 1
                resLock.wait();
            }
            // Check that raw material 1 is provided, and take raw material 1 from the resource pool
            productionChain.pop();
            // Process raw material 2
            productionChain.push(pidOfSecond);
            // printSecond.run() outputs "second". Do not change or remove this line.
            printSecond.run();
            // After processing, notify other processes to start workresLock.notifyAll(); }}Copy the code
  • * By analogy, there can be: raw material X production
    public void xth(Runnable printSecond) throws InterruptedException {
        // Deliver the tool to the manufacturer for production
        synchronized (resLock){
            // You need to check whether the resource pool has the required raw materials
            while( productionChain.empty() || productionChain.peek() ! = pidOfX_d1_th ){// pidOfX_d1_th: X decrease1 th -> (X-1)th -> (X-1
                // It is useless to get tools without raw materials, just wait for raw material X
                resLock.wait();
            }
            // Check that the raw material (X-1) is provided, and take the raw material (X-1) from the resource pool.
            productionChain.pop();
            // Process the production material x
            productionChain.push(pidOfSecond);
            // printSecond.run() outputs "second". Do not change or remove this line.
            printSecond.run();
            // After processing, notify other processes to start workresLock.notifyAll(); }}// It even feels like mathematical induction...
    Copy the code
  • Complete raw materials, assembling finished products
    public void third(Runnable printThird) throws InterruptedException {
        synchronized (resLock){
            1->2->3, and 1 and 2 should be in the same order, so we only need to check whether there is raw material 2
            while( productionChain.empty() || productionChain.peek() ! = pidOfSecond ){// wait for resource
                resLock.wait();
            }
            // The finished product is assembled from raw materials processed by the preprocessing process
            productionChain.pop();
            // Of course, this can be changed to export finished products and other operations, but at least 2 raw materials must be consumed to continue the following operations
            // printThird.run() outputs "third". Do not change or remove this line.printThird.run(); }}Copy the code
  1. Simple test line, Example 1, sequential call
    public static void main(String[] args) throws InterruptedException {
        Runnable a = () -> System.out.println("one");
        Runnable b = () -> System.out.println("two");
        Runnable c = () -> System.out.println("three");
    
        ProductionLine pl = new ProductionLine();
        pl.first(   a   );
        pl.second(  b   );
        pl.third(   c   );
        // one
        // two
        // three
    }
    Copy the code
  2. Simple test line, Example 2, out of order call
    public static void main(String[] args) throws InterruptedException {
        Runnable a = () -> System.out.println("one");
        Runnable b = () -> System.out.println("two");
        Runnable c = () -> System.out.println("three");
    
        ProductionLine pl = new ProductionLine();
        pl.first(   a   );
        pl.second(  c   ); //先跑c
        pl.third(   b   ); / / run b again
        // see if the output is still sequential
        // one
        // two
        // three
        // OK, no problem
    }
    Copy the code

Answer key

class Foo {
    Three methods need to be called, the latter two depending on the first two respectively
    // There are dependencies: 1 -> 2 -> 3
    // Two raw material ids are given here. If there are more dependent conditions, more should be considered
    private final int pidOfFirst = 1;
    private final int pidOfSecond = 2;
    // At the same time, a resource lock is required, which can be used as a limited production equipment in a production plant. Only one raw material can be produced or processed at the same time
    private final Object resLock = new Object();
    
    private Stack<Integer> productionChain ;
    public Foo(a) {
        // Init Resources Pool
        productionChain = new Stack<>();
    }
    
    public void first(Runnable printFirst) throws InterruptedException {
        // Deliver the tool to the manufacturer for production
        synchronized (resLock){
            // Make the product
            productionChain.push(pidOfFirst);
            // printFirst.run() outputs "first". Do not change or remove this line.
            printFirst.run();
            // When production is completed, inform other processes to start workresLock.notifyAll(); }}public void second(Runnable printSecond) throws InterruptedException {
        // Deliver the tool to the manufacturer for production
        synchronized (resLock){
            // You need to check whether the resource pool has the required raw materials
            while( productionChain.empty() || productionChain.peek() ! = pidOfFirst ){// It is useless to get tools without raw materials, just wait for raw material 1
                resLock.wait();
            }
            // Check that raw material 1 is provided, and take raw material 1 from the resource pool
            productionChain.pop();
            // Process raw material 2
            productionChain.push(pidOfSecond);
            // printSecond.run() outputs "second". Do not change or remove this line.
            printSecond.run();
            // After processing, notify other processes to start workresLock.notifyAll(); }}public void third(Runnable printThird) throws InterruptedException {
        synchronized (resLock){
            1->2->3, and 1 and 2 should be in the same order, so we only need to check whether there is raw material 2
            while( productionChain.empty() || productionChain.peek() ! = pidOfSecond ){// wait for resource
                resLock.wait();
            }
            // The finished product is assembled from raw materials processed by the preprocessing process
            productionChain.pop();
            // Of course, this can be changed to export finished products and other operations, but at least 2 raw materials must be consumed to continue the following operations
            // printThird.run() outputs "third". Do not change or remove this line.printThird.run(); }}}Copy the code

Afterword.

Recalling thread creation, communication, and the use of locks, it is interesting to brush up on the topic in relation to a real-world scenario 😀