问题:从0打印到99
约束:有三个线程 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");
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.IllegalMonitorStateException 异常
经检查,发现 n 在 n+=5 之后,已经变成了另一个对象,也就是 n 已经变了
以此类推,其他的基本类型也是这样,因为 Integer类中 保存的值为 private 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");
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();
}
}
这个事件给我们的教训是,不要把锁加在 Integer 等基本类型上