我有一个问题,我必须以这样的格式打印数字。
First 1
First 2
Second 3
Second 4
First 5
First 6
Second 7
Second 8
First 9
and so on...我已经实现了我的可运行的接口如下。
class ThreadDemo implements Runnable {
public volatile Integer num;
public Object lock;
public ThreadDemo(Integer num, Object lock) {
this.num = num;
this.lock = lock;
}
@Override
public void run() {
try {
while (true) {
int count = 0;
synchronized(lock) {
Thread.sleep(100);
while (count < 2) {
System.out.println(Thread.currentThread().getName() + " " + num++);
count++;
}
lock.notify();
lock.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}我的主要课程如下
public class CoWorkingThreads {
private static volatile Integer num = new Integer(1);
public static void main(String...args) {
Object lock = new Object();
Thread thread1 = new Thread(new ThreadDemo(num, lock), "First");
thread1.start();
Thread thread2 = new Thread(new ThreadDemo(num, lock), "Second");
thread2.start();
}
}当我运行程序时,我得到的输出如下
First 1
First 2
Second 1
Second 2
First 3
First 4
Second 3
Second 4而不是以前预期的结果。但是,当我将整数更改为原子整数类型时,我就开始得到预期的结果。有谁能解释一下我能做些什么来让它用整数来运行而不是使用原子整数
发布于 2019-02-19 03:43:10
我仍然认为这个问题没有得到正确的回答。这里的缺陷是,您从未将共享数据标记为static。所以每个线程都有自己的副本,独立于另一个线程。Integer是一个不可变的包装类,这是真的,但是它在这个上下文中没有任何作用。让我们更深入地研究num++。++运算符仅适用于(基本)整数类型。在幕后,num被取消装箱,++被应用,然后结果被分配回num (在装箱转换之后)。Integer类没有++运算符。实际上,Integer对象是不可变的。
不变意味着每次增加和创建一个新的值对象时。这个新值对象被分配回您的num引用。但是两个线程有自己的num引用副本,指向不同的Integer装箱原语。因此,它们彼此独立地增加它,这对另一个人来说是不可见的。如果您想在线程之间共享它,则必须在声明站点使用static访问修饰符。将两个值传递给共享变量是没有意义的。相反,您可以内联地初始化它。这是固定版本。
public class ThreadDemo implements Runnable {
public static Integer num = 1;
public static final Object lock = new Object();
public ThreadDemo() {
}
@Override
public void run() {
try {
while (true) {
int count = 0;
synchronized (lock) {
Thread.sleep(100);
while (count < 2) {
System.out.println(Thread.currentThread().getName() + " " + num++);
count++;
}
lock.notify();
lock.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class CoWorkingThreads {
public static void main(String[] args) {
Thread thread1 = new Thread(new ThreadDemo(), "First");
thread1.start();
Thread thread2 = new Thread(new ThreadDemo(), "Second");
thread2.start();
}
}最后,使用客户端提供的锁对象违反了同步策略的封装。因此,我使用了内部私有锁对象。
这是新的输出。
前1前2秒3秒4前5前6秒7秒8前9前10
发布于 2019-02-18 18:59:54
Java Integer不能通过引用传递。在您的代码中,每个线程将创建变量的副本。然而,atomicInteger可以通过引用传递。
此外,要获得正确的结果,可以将num变量更改为静态变量。
public static Integer num = 1;
public Object lock;
public ThreadDemo(Integer num, Object lock) {
//this.num = num;
this.lock =lock;
}https://stackoverflow.com/questions/54753524
复制相似问题