从网易的一道多线程笔试题学习wait与notify来控制线程同步

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从网易的一道多线程笔试题学习wait与notify来控制线程同步相关的知识,希望对你有一定的参考价值。

题目 : 有三个线程分别打印A、B、C,请用多线程编程实现,在屏幕上循环打印10次ABCABC… 

package my.thread.test;

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

public class PrintThreadExample {
    public static void main(String[] args) {
    PrintThreadExample example = new PrintThreadExample();

    LetterPrinter letterPrinter = example.new LetterPrinter();

    ExecutorService service = Executors.newFixedThreadPool(3);

    service.execute(example.new PrintRunnable(letterPrinter, ‘A‘));
    service.execute(example.new PrintRunnable(letterPrinter, ‘B‘));
    service.execute(example.new PrintRunnable(letterPrinter, ‘C‘));

    service.shutdown();
  }

  private class LetterPrinter {
      private char letter = ‘A‘;

    public void print() {
      System.out.println(letter);
      if (‘C‘ == letter) {
        System.out.println();
      }
    }

    public void nextLetter() {
      switch (letter) {
      case‘A‘:
        letter = ‘B‘;
        break;
      case‘B‘:
        letter = ‘C‘;
        break;
      case‘C‘:
        letter = ‘A‘;
        break;
      }
    }

    /**
     * @return the letter
     */public char getLetter() {
      return letter;
    }

  }

  private class PrintRunnable implements Runnable {
    private LetterPrinter letterPrinter = null;

    private char letter = ‘ ‘;

    /**
     * @param letterPrinter
     * @param letter
     */public PrintRunnable(LetterPrinter letterPrinter, char letter) {
      super();
      this.letterPrinter = letterPrinter;
      this.letter = letter;
    }

    public void run() {
      for (int i = 0; i < 10; i++) {
        //synchronized (letterPrinter) {
          while (letter != letterPrinter.getLetter()) {
            try {
              letterPrinter.wait();
            } catch (InterruptedException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
            }
         // }

          letterPrinter.print();
          letterPrinter.nextLetter();
          letterPrinter.notifyAll();

        }
      }

    }

  }

}
Exception in thread "pool-1-thread-2" Exception in thread "pool-1-thread-3" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Unknown Source)
    at my.thread.test.PrintThreadExample$PrintRunnable.run(PrintThreadExample.java:72)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Unknown Source)
    at my.thread.test.PrintThreadExample$PrintRunnable.run(PrintThreadExample.java:72)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

如果注释掉synchronized (letterPrinter) 则会抛出IllegalMonitorStateException异常,查了一下文档,如下:

技术分享

如果当前线程不是对象监视器的拥有者的话则会抛出IllegalMonitorStateException异常。也就是当需要调用一个对象的wait方法的时候,首先需要获取这个对象,否则会出现问题。Statck上一个回答解释了原因,如下:

 技术分享

技术分享

这个例子说明了加锁的原因之一是为了操作原子性,以免引起死锁的问题

以上是关于从网易的一道多线程笔试题学习wait与notify来控制线程同步的主要内容,如果未能解决你的问题,请参考以下文章

经典笔试题:两个线程交替打印奇偶数

JAVA多线程之wait/notify

Java多线程并发面试题

多线程关于腾讯笔试题

java多线程wait notify join

Java多线程——wait方法和notify方法的详解