I’m Little Xia Lufei. Learning shapes our lives. Technology changes the world.

The article directories

    • preface
    • Wait /notifyAll
    • ReentrantLock and Condition

preface

This is the little xia in some time ago in the interview, was quick hand interviewer really asked the topic (is really quick hand interviewer, did not attract attention).

The first thread prints 1, 2, 3, 4, 5. The second thread prints 6, 7, 8, 9, 10. The third thread prints 11, 12, 13, 14, 15. And so on until you get to 60.

Wait /notifyAll

/ * * *@author Carson
 * @date2020/11/12 21:50 * /
public class Main {
    // The numeric initial value
    private static int num = 1;
    private static final int MAX = 60;
    // The execution thread's marker field, 1 indicates that thread A executes, 2 indicates that thread B executes, and 3 indicates that thread C executes
    // Use volatile to ensure visibility
    private static volatile int flag = 1;

    public static void main(String[] args) {
        Object monitor = new Object();
        Thread pOne = new Thread(new PrintOne(monitor));
        Thread pTwo = new Thread(new PrintTwo(monitor));
        Thread pThr = new Thread(new PrintThr(monitor));

        pOne.setName("Thread A");
        pTwo.setName("Thread B");
        pThr.setName(Thread "C");

        pOne.start();
        pTwo.start();
        pThr.start();

    }

    static class PrintOne implements Runnable {
        final Object monitor;

        public PrintOne(Object monitor) {
            this.monitor = monitor;
        }

        @Override
        public void run(a) {
            while (num < MAX) {
                synchronized (monitor) {
                	// Through an infinite loop to verify that thread A is currently executing,
                	// If not, call wait to release the lock
                    while(flag ! =1) {
                        try {
                            monitor.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.print(Thread.currentThread().getName() + "-- >");
                    for (int i = 0; i < 5; i++) {
                        System.out.print(num + "");
                        num++;
                    }
                    // Print here for line feed only
                    System.out.println();
                    // Set the flag to B to wake up thread B
                    flag = 2;
                    // Wake up other threadsmonitor.notifyAll(); }}}}static class PrintTwo implements Runnable {
        final Object monitor;

        public PrintTwo(Object monitor) {
            this.monitor = monitor;
        }

        @Override
        public void run(a) {
            while (num < MAX) {
                synchronized (monitor) {
                    while(flag ! =2) {
                        try {
                            monitor.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.print(Thread.currentThread().getName() + "-- >");
                    for (int i = 0; i < 5; i++) {
                        System.out.print(num + "");
                        num++;
                    }
                    System.out.println();
                    // Set the flag to C to wake up thread C
                    flag = 3; monitor.notifyAll(); }}}}static class PrintThr implements Runnable {
        final Object monitor;

        public PrintThr(Object monitor) {
            this.monitor = monitor;
        }

        @Override
        public void run(a) {
            while (num < MAX) {
                synchronized (monitor) {
                    while(flag ! =3) {
                        try {
                            monitor.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.print(Thread.currentThread().getName() + "-- >");
                    for (int i = 0; i < 5; i++) {
                        System.out.print(num + "");
                        num++;
                    }
                    System.out.println();
                    // Set the flag to A to wake up thread A
                    flag = 1;
                    monitor.notifyAll();
                }
            }
        }
    }

}
Copy the code

ReentrantLock and Condition

The idea is to control access to three threads through a shared ReentrantLock, which we all know is a ReentrantLock. The Condition variable allows thread A to send A signal to thread B to wake up THREAD B, and thread B to send A signal to thread C to wake up thread C, and so on.

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        / / define the lock
        ReentrantLock lock = new ReentrantLock();
        // Prints the condition of thread A
        Condition conditionA = lock.newCondition();
        // Prints the condition of thread B
        Condition conditionB = lock.newCondition();
        // Prints the condition of thread C
        Condition conditionC = lock.newCondition();
        // instantiate thread A
        Thread printerA = new Thread(new ReentrantLockSyncPrinter(lock, conditionA, conditionB));
        // instantiate thread B
        Thread printerB = new Thread(new ReentrantLockSyncPrinter(lock, conditionB, conditionC));
        // instantiate thread C
        Thread printerC = new Thread(new ReentrantLockSyncPrinter(lock, conditionC, conditionA));

        printerA.setName("Thread A");
        printerB.setName("Thread B");
        printerC.setName(Thread "C");

        printerA.start();
        Thread.sleep(100); printerB.start(); printerC.start(); }}class ReentrantLockSyncPrinter implements Runnable {
    / / initial value
    private static int num = 1;
    private static final int MAX = 60;
    // Print times
    private static final int COUNT = 5;
    / / print the lock
    final ReentrantLock reentrantLock;
    // This thread prints the required condition
    final Condition currCondition;
    // The next thread prints the required condition
    final Condition nextCondition;

    public ReentrantLockSyncPrinter(ReentrantLock reentrantLock, Condition currCondition, Condition nextCondition) {
        this.reentrantLock = reentrantLock;
        this.currCondition = currCondition;
        this.nextCondition = nextCondition;
    }

    @Override
    public void run(a) {
        // Get the lock and enter the critical section
        reentrantLock.lock();
        try {
            while (num < MAX) {
                System.out.print(Thread.currentThread().getName() + "-- >");
                // Print COUNT times
                for (int i = 0; i < COUNT; i++) {
                    // Prints characters
                    System.out.print(num + "");
                    num++;
                }
                System.out.println();
                // Wake up the next thread with nextCondition
                // Since only one thread is waiting, either signal or signalAll can be used
                nextCondition.signal();
                try {
                    // The thread relinquishes the lock and waits to wake up
                    currCondition.await();
                } catch(InterruptedException e) { e.printStackTrace(); }}}finally {
            / / releases the lockreentrantLock.unlock(); }}}Copy the code