我有一个问题,我必须以这种格式打印数字。
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
代替以前的预期结果。但是,当我将整数更改为原子整数类型时,我开始获得预期的结果。谁能解释我该怎么做才能使它以整数而不是原子整数运行
答案 0 :(得分:1)
不能通过引用传递Java Integer。在您的代码上,每个线程都会创建该变量的副本。但是atomicInteger可以通过引用传递。
另外,要获得正确的结果,可以将num变量更改为static变量。
public static Integer num = 1;
public Object lock;
public ThreadDemo(Integer num, Object lock) {
//this.num = num;
this.lock =lock;
}
答案 1 :(得分:0)
答案 2 :(得分:0)
仅就您所知,您可能不希望在synchronized
上使用Object
(例如Lock
),而在ReentrantLock
上使用Condition
块,并且他们关联的Condition
。
使用Public Function OleDragEnter(<[In]> <MarshalAs(UnmanagedType.Interface)> pDataObj As Object, <[In]> <MarshalAs(UnmanagedType.U4)> grfKeyState As Integer, <[In]> <MarshalAs(UnmanagedType.U8)> pt As Long, <[In]> <Out> ByRef pdwEffect As Integer) As Integer Implements IOleDropTarget.OleDragEnter
Dim x As Integer = CInt(pt And &H7FFFFFFF)
Dim y As Integer = CInt((pt >> 32) And &H7FFFFFFF)
Dim winPT As Win32Point
winPT.x = CInt(pt And &H7FFFFFFF)
winPT.y = CInt((pt >> 32) And &H7FFFFFFF)
ddHelper.DragEnter(hwnd, CType(pDataObj, NativeMethods.IDataObject), winPT, 0)
End Function
(s),可以在线程之间以互斥的方式管理共享资源。
答案 3 :(得分:0)
我仍然认为此问题未得到正确回答。此处的缺陷是您从未将共享数据标记为static
。因此,每个线程都有自己的副本,彼此独立。 Integer
是一个不变的包装器类,这是对的,但是在这种情况下它无关紧要。让我们深入研究num++
。 ++
运算符仅适用于(原始)整数类型。在幕后,将num
取消装箱,应用++
,然后将结果分配回num
(在装箱转换之后)。 Integer
类没有++
运算符。实际上,Integer
对象是不可变的。
Immutable表示每次递增并创建新的值对象时。并将该新值对象分配回您的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