[Java multithreaded programming problem] two threads loop output A and B

This is a programming problem of Jingdong interview

This question is very interesting. I just learned the basic Java multithreading, so I'll try it. Note that wait() needs to be placed in the while loop to avoid missing the notify signal

A better scheme of code style: synchronization method

package thread.print;

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

public class CyclicPrint {
    private ExecutorService executorService = Executors.newFixedThreadPool(2);
    private boolean printA = true;
    private synchronized void printA() throws InterruptedException {
        while (!printA) wait();
        System.out.println("A");
        printA = false;
        notifyAll();
    }
    private synchronized void printB() throws InterruptedException {
        while (printA) wait();
        System.out.println("B");
        printA = true;
        notifyAll();
    }
    private Thread a = new Thread(() -> {
        while (!Thread.interrupted()) {
            try {
                printA();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    private Thread b = new Thread(() -> {
        while (!Thread.interrupted()) {
            try {
                printB();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    public CyclicPrint() throws InterruptedException {
        executorService.execute(a);
        executorService.execute(b);
        Thread.sleep(1000);
        executorService.shutdownNow();
    }


    public static void main(String[] args) throws InterruptedException {
        new CyclicPrint();
    }
}

Another scheme is similar to the above one, but its readability is lower: synchronization critical area

package thread.print;

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

public class CyclicPrint2 {
    private ExecutorService executorService = Executors.newFixedThreadPool(2);
    private final CyclicPrint2 p = this;
    private boolean printA = true;
    private Thread a = new Thread(() -> {
        while (!Thread.interrupted()) {
            synchronized (p) {
                while (!printA) {
                    try {
                        p.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("A");
                printA = false;
                p.notifyAll();
            }
        }
    });
    private Thread b = new Thread(() -> {
        while (!Thread.interrupted()) {
            synchronized (p) {
                while (printA) {
                    try {
                        p.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("B");
                printA = true;
                p.notifyAll();
            }
        }
    });
    public CyclicPrint2() throws InterruptedException {
        executorService.execute(a);
        executorService.execute(b);
        Thread.sleep(1000);
        executorService.shutdownNow();
    }

    public static void main(String[] args) throws InterruptedException {
        new CyclicPrint();
    }
}

Lock+Condition version

package thread.print;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class CyclicPrint3 {
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    private ExecutorService executorService = Executors.newFixedThreadPool(2);
    private boolean printA = true;
    private void printA() throws InterruptedException {
        lock.lock();
        while (!printA) condition.await();
        System.out.println("A");
        printA = false;
        condition.signalAll();
        lock.unlock();
    }
    private void printB() throws InterruptedException {
        lock.lock();
        while (printA) condition.await();
        System.out.println("B");
        printA = true;
        condition.signalAll();
        lock.unlock();
    }
    private Thread a = new Thread(() -> {
        while (!Thread.interrupted()) {
            try {
                printA();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    private Thread b = new Thread(() -> {
        while (!Thread.interrupted()) {
            try {
                printB();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    public CyclicPrint3() throws InterruptedException {
        executorService.execute(a);
        executorService.execute(b);
        Thread.sleep(1000);
        executorService.shutdownNow();
    }


    public static void main(String[] args) throws InterruptedException {
        new CyclicPrint3();
    }
}

Conclusion: at the beginning, I was still stumped by this problem, because I just finished my basic study. At first, I even used new components such as CountDownLatch or CyclicBarrier to solve this problem, but it should not work. Then I slowly think about the solution of synchronization + cycle condition, and the effect is good.

Tags: Java Programming

Posted on Wed, 04 Dec 2019 06:10:06 -0800 by Jnerocorp