![](/img/trans.png)
[英]Thread synchronization/producer-consumer in java. Printing out numbers 1-10 then 10-1 repeatedly
[英]Java Thread synchronization - printing out numbers in right order
我正在學習如何在Java中使用線程,我需要一些建議。
我想在0..50的標准輸出數字上打印使用三個線程完成的線程的名稱。
我有兩個類-實現Runnable的Counter 類和創建並運行線程的Main類 。 計數器具有在線程之間共享的變量c 。
我的想法是,我將c加1,然后在當前線程上調用yield() ,以便其他線程也可以這樣做。 重復此操作,直到c達到50。
但這不起作用,數字打印順序錯誤。 我該如何解決?
public class Counter implements Runnable {
Thread t1;
private int c = -1;
public Counter() {
}
public Counter(String name) {
t1 = new Thread(this, name);
t1.start();
}
@Override
public void run() {
while (c < 50) {
increment();
Thread.yield();
}
}
public void increment() {
if (c < 50) {
c++;
System.out.println(Thread.currentThread().getName() + ": " + c);
}
}
}
public class Main {
public static void main(String[] args) throws IllegalThreadStateException {
Counter c1 = new Counter();
Thread t1 = new Thread(c1, "Thread 1");
Thread t2 = new Thread(c1, "Thread 2");
Thread t3 = new Thread(c1, "Thread 3");
t1.start();
t2.start();
t3.start();
}
編輯:最終我以這種方式解決了它。 謝謝所有幫助我艱難地開始多線程工作的人。
import java.util.concurrent.atomic.AtomicInteger;
public class Counter2 implements Runnable {
// you could also use simple int
private AtomicInteger c = new AtomicInteger(-1);
private static final Object syncObject = new Object();
public Counter2() {
}
@Override
public void run() {
while (c.get() < 50) {
synchronized (syncObject) {
if (c.get() < 50) {
System.out.println(Thread.currentThread().getName() + ": " + c.incrementAndGet());
}
}
}
}
}
在帶有特殊靜態對象的方法增量中使用同步部分。
private static final Object syncObj = new Object();
public void increment()
{
syncrhonized( syncObj )
{
c++;
System.out.println(c);
}
}
或通過其聲明使此方法同步。
但是將實際數據存儲在線程對象中是錯誤的想法。 線程應該只使用共享對象進行操作,而不要存儲它們。\\實際上我不明白為什么要在其中啟動線程
使increment()
同步,以防止其他線程同時進入方法。
與yield()
結合使用,您應該能夠使另一個線程打印下一個數字(並非總是如此,因為系統可能會再次恢復調用yield
的線程-請參閱Ingo的答案-,但順序應相同)。
synchronized increment()
意味着,如果另一個線程通過輸入方法已經獲取了鎖,則試圖在同一對象上輸入該方法的任何線程都必須等待。
引用javadoc Thread.yield(),我強調:
public static void yield()
給調度程序的提示是當前線程願意放棄當前使用的處理器。 調度程序可以隨意忽略此提示 。
...
很少適合使用此方法。
是的,您的代碼無效。 Thread#yield()不會以您期望的方式控制線程調度程序。 我很好奇您會得到什么結果。您可能會得到重復的數字,有些數字會有些混亂。
您可以使用原子整數,該整數應刪除所有重復項。 但是由於print語句不是原子的。 您仍然可以不按順序打印結果。 因此,您可能應該僅同步增量方法。 另外,您實際上並不需要產量,所以將其丟棄。
如果問題的目的是從線程1到線程2再到線程3再回到線程1,依此類推,那么結果是
Thread 1:0
Thread 2:1
Thread 3:2
Thread 1:3
Thread 2:4
Thread 3:5
Thread 1:6
Thread 2:7
....
然后,您需要鎖定增量方法,並使用wait和notifyAll。 等待將導致其他線程停止處理,直到當前線程通知它們再次啟動。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.