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

The article directories

    • preface
    • Analysis of interview questions
    • Wait/Notify for Object
    • Control by a volatile variable
    • This is implemented through the atomic variable AtomicInteger and the latch CountDownLatch

preface

Java multithreading this is a popular knowledge point of the enterprise interview, the interviewer also likes to let candidates handwritten part of the code, mainly in order to examine the candidate’s understanding of the thread synchronization mechanism and the use of proficiency. Problems such as starting two threads to alternately print odd and even numbers from 1 to 100 pop up.

Analysis of interview questions

To print odd and even alternately is to start two threads to achieve the following effect:

Strange threads:1Accidentally thread:2... Strange threads:99Accidentally thread:100
Copy the code

Simple analysis, the first is two threads, and the second is alternate sequence printing. This relates to communication between threads. In this case, the general direction is to lock, which thread holds the lock print, then release the lock and let the other thread take the lock. The two threads take turns to acquire the lock, achieving the effect of alternate printing.

Wait/Notify for Object

The wait()/notify() mechanism of the Object class is the first thing you can think of for thread communication.

When there are multiple threads processing the wait state, notify() wakes up one of them randomly. If you want to wake up all of them, you should call notifyAll().

At this point, we should define two threads, one to print an odd number and one to print an even number, and both threads hold the same object lock (which can be injected by the constructor), thus ensuring synchronization between threads. Here are three things to note:

  • Shared variablesnumberWe all know that we can’t do anything until the lock is acquired in both threads++The operation is non-atomic, but in this case the lock ensures that only one thread can operate at a time, so it is not neededAtomicIntegerAtomic variables of this sort.
  • For odd threads, if the current number is even (the opposite is true for even threads), the wait() method is called to block the wait, and if it is odd, the print is performed, incremented, and the other thread is woken up with notify().
  • If the number of odd threads is an even number, wait() will be called. If the number of odd threads is an even number, wait() will be called.
public class Main {
    private static volatile int number = 1;
    private static final int MAX = 100;

    public static void main(String[] args) {
        Object monitior = new Object();
        Thread oddThread = new Thread(new OddThread(monitior));
        oddThread.setName(Odd thread);
        Thread evenThread = new Thread(new EvenThread(monitior));
        evenThread.setName("Even thread");
        oddThread.start();
        evenThread.start();
    }

    /** * odd threads */
    static class OddThread implements Runnable {
        private Object monitor;

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

        @Override
        public void run(a) {
            while (number < MAX) {
                synchronized (monitor) {
                    while (number % 2= =0) {
                        try {
                            monitor.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName() + "-- >"+ number); number++; monitor.notify(); }}}}/** ** even threads */
    static class EvenThread implements Runnable {
        private Object monitor;

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

        @Override
        public void run(a) {
            while (number <= MAX) {
                synchronized (monitor) {
                    while (number % 2! =0) {
                        try {
                            monitor.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName() + "-- >" + number);
                    number++;
                    monitor.notify();
                }
            }
        }
    }

}
Copy the code

Control by a volatile variable

The idea is that the thread loops through volatile variables indefinitely until they become false. When it becomes false, the thread actually executes the business logic, prints the numbers, and finally needs to suspend itself and modify the volatile variable to wake up other threads.

public class Main {
    private static volatile int number = 1;
    private static final int MAX = 100;
    private static volatile boolean flag = true;

    public static void main(String[] args) {
        Thread oddThread = new Thread(new OddThread());
        oddThread.setName(Odd thread);
        Thread evenThread = new Thread(new EvenThread());
        evenThread.setName("Even thread");
        oddThread.start();
        evenThread.start();
    }

    /** * odd threads */
    static class OddThread implements Runnable {
        @Override
        public void run(a) {
            while (number < MAX) {
                while (flag) {
                    System.out.println(Thread.currentThread().getName() + "-- >" + number);
                    number++;
                    flag = false; }}}}/** ** even threads */
    static class EvenThread implements Runnable {
        @Override
        public void run(a) {
            while (number <= MAX) {
                while(! flag) { System.out.println(Thread.currentThread().getName() +"-- >" + number);
                    number++;
                    flag = true;
                }
            }
        }
    }

}
Copy the code

This is implemented through the atomic variable AtomicInteger and the latch CountDownLatch

public class Main {
    private static ExecutorService executorService = new ThreadPoolExecutor(2.5.1000L,
            TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024));

    private static CountDownLatch countDownLatch = new CountDownLatch(2);
    private static volatile boolean flag = false;
    private static AtomicInteger num = new AtomicInteger(1);
    private static final Integer MAX = 100;

    public static void main(String[] args) throws InterruptedException {
        executorService.submit(new Runnable() {
            @Override
            public void run(a) {
                while (num.get() <= MAX ) {
                    if(! flag) { System.out.println(Thread.currentThread().getName() +"-- >" + num.getAndIncrement());
                        flag = true; } } countDownLatch.countDown(); }}); executorService.submit(new Runnable() {
            @Override
            public void run(a) {
                while (num.get() <= MAX) {
                    if (flag) {
                        System.out.println(Thread.currentThread().getName() + "-- >" + num.getAndIncrement());
                        flag = false; } } countDownLatch.countDown(); }}); countDownLatch.await(); }}Copy the code

I’m Luffy. I’ll see you next time.