我正在尝试使用多个线程中的共享整数对象按顺序打印从1到10的数字。当使用共享对象作为AtomicInteger时,程序可以正常工作,但是当使用普通的Integer对象时,程序会引发异常,我不知道为什么会发生这种情况。
使用AtomicInteger的程序
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadingProblem {
public static void main(String[] args) {
AtomicInteger sharedInt = new AtomicInteger(0);
Thread t1 = new Thread(new ThreadingPrintingTask(sharedInt), "PrinterThread");
Thread t2 = new Thread(new ThreadingIncrementingTask(sharedInt), "IncrementerThread");
t1.start();
t2.start();
}
}
class ThreadingPrintingTask implements Runnable {
private AtomicInteger sharedObject;
public ThreadingPrintingTask(AtomicInteger sharedObject) {
this.sharedObject = sharedObject;
}
@Override
public void run() {
try {
synchronized (sharedObject) {
while (true) {
sharedObject.wait();
System.out.println("Shared object value is: " + sharedObject);
sharedObject.notify();
}
}
}
catch (InterruptedException e) {
}
}
}
class ThreadingIncrementingTask implements Runnable {
private AtomicInteger sharedObject;
public ThreadingIncrementingTask(AtomicInteger sharedObject) {
this.sharedObject = sharedObject;
}
@Override
public void run() {
synchronized (sharedObject) {
while (this.sharedObject.get() < 10) {
this.sharedObject.incrementAndGet();
this.sharedObject.notify();
try {
this.sharedObject.wait();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
输出
Shared object value is: 1
Shared object value is: 2
Shared object value is: 3
Shared object value is: 4
Shared object value is: 5
Shared object value is: 6
Shared object value is: 7
Shared object value is: 8
Shared object value is: 9
Shared object value is: 10
带有普通整数对象的程序
public class ThreadingProblem {
public static void main(String[] args) {
Integer sharedInt = new Integer(0);
Thread t1 = new Thread(new ThreadingPrintingTask(sharedInt), "PrinterThread");
Thread t2 = new Thread(new ThreadingIncrementingTask(sharedInt), "IncrementerThread");
t1.start();
t2.start();
}
}
class ThreadingPrintingTask implements Runnable {
private Integer sharedObject;
public ThreadingPrintingTask(Integer sharedObject) {
this.sharedObject = sharedObject;
}
@Override
public void run() {
try {
synchronized (sharedObject) {
while (true) {
sharedObject.wait();
System.out.println("Shared object value is: " + sharedObject);
sharedObject.notify();
}
}
}
catch (InterruptedException e) {
}
}
}
class ThreadingIncrementingTask implements Runnable {
private Integer sharedObject;
public ThreadingIncrementingTask(Integer sharedObject) {
this.sharedObject = sharedObject;
}
@Override
public void run() {
synchronized (sharedObject) {
while (this.sharedObject < 10) {
this.sharedObject++;
this.sharedObject.notify();
try {
this.sharedObject.wait();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
输出
Exception in thread "IncrementerThread" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at com.itiviti.apps.catalys.shared.mock.ThreadingIncrementingTask.run(ThreadingProblem.java:52)
at java.lang.Thread.run(Unknown Source)
答案 0 :(得分:8)
this.sharedObject++;
并没有您想象的那样。
由于Integer
是不可变的,因此无法更改现有共享对象。相反,此操作要做的是将值装箱到int
中,将其递增,然后将其装箱到另一个Integer
实例中。
因此,您的代码(几乎*)等效于以下内容:
int temp = this.sharedObject.intValue();
temp = temp + 1;
this.sharedObject = new Integer(temp);
由于此时您的对象不再是同一实例,因此您的synchronized
块将不会与wait()
/ notify()
调用对齐。
请注意,这与AtomicInteger
的原子性无关,只是与++
运算符在Integer
上的工作方式有关。
*实际上,您可能会获得一个缓存的实例而不是new Integer()
,但是它仍然是一个不同的实例,因为它代表了一个不同的int
值。 >