美文网首页
一道多线程编程面试题

一道多线程编程面试题

作者: 周群力 | 来源:发表于2019-08-10 11:37 被阅读0次

    看到一道多线程面试题,看起来很简单但是仔细想想有些细节很容易踩坑,因此记录一下。

    题目来源:https://juejin.im/post/5c89b9515188257e5b2befdd

    题目:

    评论:

    这题用信号量数组、用Monitor(一个lock和condition数组)都能做。用信号量的解法上述链接里有,这里说下用Monitor解题存在的坑:

    1. 如果代码写成了主线程初始化并start了所有线程后,直接condition.signal通知第一个线程,可能会存在问题:假如第一个线程还没有被调度、还没有执行condition.await,此时condition.signal会在condition.await之前执行,这次通知就丢掉了(但是信号量就可以先release再aquire,先通知再等待)所以为避免这种情况,还得加个countDownLatch保证所有线程的任务都执行过之后,主线程再获取锁、condition.signal通知第一个线程起跑;

    2. 用condition.signal或await的前提是当前线程持有该锁(信号量就没有这种限制,可以看链接里给的信号量实现方案)

    用Monitor解题的代码:

    public class LoopPrinter {

    private final PrintTask[]tasks;

    private final int            number;

    private final Thread[]threads;

    private final ReentrantLocklock    =new ReentrantLock();

    private final Condition[]conditions;

    private      Integercounter = -1;

    private final CountDownLatchinitedLatch;

    public CountDownLatch getInitedLatch() {

    return initedLatch;

    }

    public ReentrantLock getLock() {

    return lock;

    }

    public Condition[] getConditions() {

    return conditions;

    }

    public LoopPrinter(int number) {

    if (number <=0) {

    throw new IllegalArgumentException("The number must be positive.");

    }

    this.number = number;

    threads =new Thread[number];

    tasks =new PrintTask[number];

    conditions =new Condition[number];

    initedLatch =new CountDownLatch(number);

    for (int i =0; i < number; i++) {

    PrintTask printTask =new PrintTask(this, i);

    tasks[i] = printTask;

    threads[i] =new Thread(printTask);

    conditions[i] =lock.newCondition();

    }

    }

    public void start() {

    for (int i =0; i

    threads[i].start();

    }

    try {

    initedLatch.await();

    tasks[0].go();

    }catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    public static void main(String[] args)throws InterruptedException {

    LoopPrinter printer =new LoopPrinter(3);

    printer.start();

    Thread.sleep(3000);

    }

    private static class PrintTaskimplements Runnable {

    private LoopPrinterprinter;

    private int        index;

    public PrintTask(LoopPrinter loopPrinter,int i) {

    this.printer = loopPrinter;

    index = i;

    }

    @Override

            public void run() {

    //取锁

                printer.getLock().lock();

    try {

    while (true) {

    Condition[] conditions =printer.getConditions();

    printer.getInitedLatch().countDown();

    Condition condition = conditions[index];

    condition.await();

    int counter =printer.increCounter();

    if (counter >100) {

    System.exit(0);

    }

    System.out.println("Thread " +index +":" + counter);

    int nextIdx = (index +1) % conditions.length;

    conditions[nextIdx].signal();

    }

    }catch (InterruptedException e) {

    e.printStackTrace();

    }finally {

    printer.getLock().unlock();

    }

    }

    public void go() {

    printer.getLock().lock();

    try {

    Condition[] conditions =printer.getConditions();

    Condition condition = conditions[index];

    condition.signal();

    }finally {

    printer.getLock().unlock();

    }

    }

    }

    private int increCounter() {

    counter +=1;

    return counter;

    }

    }

    相关文章

      网友评论

          本文标题:一道多线程编程面试题

          本文链接:https://www.haomeiwen.com/subject/unaljctx.html