Javaマルチスレッドの数字を印刷します。


問題:0から99まで印刷します。
制約:3つのスレッドA、B、Cがあり、そのうちAは0~4をプリントし、Bは5~9をプリントし、Cは10~14をプリントし、Aは15~19をプリントし、Bは20~24をプリントし、これを類推する。
まず、コードを書きました。次のように。
public class PrintThread extends Thread {

	private int id;

	private static Integer n = 0;

	public PrintThread(int id) {
		this.id = id;
	}

	@Override
	public void run() {
		while (n < 100) {
			synchronized (n) {
				while ((n % 5 != 0) || (n % 5 == 0 && (n / 5) % 3 != id)) {
					try {
						n.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				if (n < 100) {
					System.out.print("Thread-" + id + " : " + n + " " + (n + 1)
							+ " " + (n + 2) + " " + (n + 3) + " " + (n + 4)
							+ "
"); n += 5; } n.notifyAll(); } } } public static void main(String[] args) { Thread t0 = new PrintThread(0); Thread t1 = new PrintThread(1); Thread t2 = new PrintThread(2); t0.start(); t1.start(); t2.start(); } }
結果として問題が発生します。n.notifyAllの時にjava.lang.IllgalMonitoStation異常を報告します。
nはn+=5の後にもう一つの対象になりました。つまりnはもう変わりました。
これを類推すると、他の基本タイプも同じです。Integer類に保存されている値はprvate final int valueです。
次のコードに変更すればいいです。
public class PrintThread extends Thread {

	private int id;

	private static Integer n = 0;

	private static final Object lock = new Object();

	public PrintThread(int id) {
		this.id = id;
	}

	@Override
	public void run() {
		while (n < 100) {
			synchronized (lock) {
				while ((n % 5 != 0) || (n % 5 == 0 && (n / 5) % 3 != id)) {
					try {
						lock.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				if (n < 100) {
					System.out.print("Thread-" + id + " : " + n + " " + (n + 1)
							+ " " + (n + 2) + " " + (n + 3) + " " + (n + 4)
							+ "
"); n += 5; } lock.notifyAll(); } } } public static void main(String[] args) { Thread t0 = new PrintThread(0); Thread t1 = new PrintThread(1); Thread t2 = new PrintThread(2); t0.start(); t1.start(); t2.start(); } }
この事件が教えてくれたのは、インテグなどの基本タイプにロックをかけないことです。