【Java多线程编程题】两个线程循环输出A和B

非个人面试,这是京东面试的一道编程题

前言:这道题挺有意思的,刚好我刚学了基础的Java多线程,那就试一试。另外以下的两种方案都需要注意就是,wait()需要放在while循环里以防错失notify信号


一种代码风格比较好的方案:同步方法

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

另外一种与上面大同小异的方案,但是可读性较之低一些:同步临界区

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

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

结语:使用同步+循环条件的解决方案效果还不错。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。