[英]Threads synchronization in Java
我有一個類似的場景。...有四個線程分別命名為Thread1,Thread2,Thread3和Thread4。 並且有一個計數器變量。 我想輸出如下
Thread1 : value of counter variable is = 0
Thread2 : value of counter variable is = 1
Thread3 : value of counter variable is = 2
Thread4 : value of counter variable is = 3
Thread1 : value of counter variable is = 4
Thread2 : value of counter variable is = 5
Thread3 : value of counter variable is = 6
Thread4 : value of counter variable is = 7
Thread1 : value of counter variable is = 8
Thread2 : value of counter variable is = 9
Thread3 : value of counter variable is = 10
Thread4 : value of counter variable is = 11
甚至我在邏輯上也做到了。 但是我想要類似的東西,當Thread1正在打印counter變量時,所有其余線程都應等待.....然后在Thread2之后出現圖片並打印counter變量,其余應等待。
建議我為此的最佳解決方案。 提前致謝 :-)
除了了解同步,這幾乎沒有意義。 我會使用CyclicBarrier
來做到這一點。 這是一個相當高級的抽象,因此您不必自己使用wait()
或notifiy()
。
或者,您可以使用Integer
或AtomicInteger
對象作為變量,並將其傳遞到線程周圍(每個對象都應提供可被另一個線程調用的consume(Integer i)
方法,然后遞增並打印該值並將其傳遞給下一個螺紋)。 在此變體中,同步在代碼中隱式處理。
我不確定你想要什么。 您是否要讓線程按順序增加並打印變量? 這沒有任何意義,線程是獨立的,並且可以同時運行。 那就是他們的目的。
因此,讓我直接講:您想使用並行處理來進行串行工作。
基本上,您要做的是:
for(int i=0;i<10;i++)
System.out.println(i);
但是然后有線程。
線程用於並行處理事務。 那就是他們的目的。 試圖將串行問題強加給這個概念,不僅會減慢您的應用程序的速度,而且會使它更容易出錯。
當然,除非您的這個示例非常簡化。 也許您需要提供更多信息以幫助我們,然后...
這是一個有趣的問題,因為線程被設計為獨立地並排工作,而不是嚴格地鎖定在一起。
我認為最簡單的方法是使用公平的ReentrantLock , AtomicInteger和一些謹慎的設置(以確保線程以正確的順序開始在ReentrantLock上等待)。
您的主線程將需要初始化計數器,創建鎖對象並對其進行鎖定,然后依次啟動四個子線程,確保在關閉下一個線程之前,每個子線程都到達了鎖。
當所有4個線程准備就緒時,您可以釋放鎖並讓其他線程運行。
每個工作線程應從計數器中獲取值,將其遞增,顯示計數器,然后釋放鎖(這將使下一個線程運行),然后再重新獲取它。
請注意,這里仍然存在競爭條件:線程2可能在線程1開始再次等待鎖之前繞循環運行,因此這兩個線程最終將以相反的順序運行。 要解決此問題,輔助線程需要等待,直到有足夠多其他線程在等待,直到它們在循環中繼續進行為止(當然,最后一次迭代除外)。 不太好,但是由於列出的限制,我擔心這很重要。
這不是簡單的代碼。 我認為,這里要學習的教訓是,您不應該真正使用多個線程來執行固有的串行工作! 要么,要么您不必在乎哪個線程執行哪個串行操作。
我找到了解決此問題的兩種方法。...但仍在等待專家評論...。
第一種方式:-----
包semafore;
導入java.util.concurrent.Semaphore;
公共類Main {公共靜態void main(String args [])引發異常{Semaphore sem = new Semaphore(1,true); 線程thrdA = new Thread(new SyncOutput(sem,“ Thread1”)); 線程thrdB = new Thread(new SyncOutput(sem,“ Thread2”)); 線程thrdC =新線程(新SyncOutput(sem,“ Thread3”)); 線程thrdD =新線程(新SyncOutput(sem,“ Thread4”));
thrdA.start();
thrdB.start();
thrdC.start();
thrdD.start();
thrdA.join();
thrdB.join();
thrdC.join();
thrdD.join();
}
}
SyncOutput類實現Runnable {Semaphore sem; 字符串味精; 私有靜態int val = 0;
SyncOutput(Semaphore s, String m) {
sem = s;
msg = m;
}
public void run() {
for (int i = 0; i < 3; i++){
try {
sem.acquire(1);
System.out.println(msg + " : " + ++val);
Thread.sleep(1000);
} catch (Exception exc) {
System.out.println("Error Writing File");
}
sem.release(1);
}
}
}
第二種方式:-----
包線程;
class num {
// state variable identifying whose turn it is.
private String whoseTurn ="A";
private int cnt=0;
public boolean writenum(String who) {
String x = Thread.currentThread().getName();
try{
Thread.sleep(1000);
}catch(Exception e){}
if (x.equalsIgnoreCase(whoseTurn)) {
System.out.println(x+":"+cnt++);
if(x.equalsIgnoreCase("A"))
whoseTurn = "B";
else if(x.equalsIgnoreCase("B"))
whoseTurn = "C";
else if( x.equalsIgnoreCase("C"))
whoseTurn = "D";
else if( x.equalsIgnoreCase("D"))
whoseTurn = "A";
}
return true;
}
}
public class Game {
public static void main(String args[]) {
num ob = new num();
Thread A = new Thread(new Player("A", ob));
Thread B = new Thread(new Player("B", ob));
Thread C = new Thread(new Player("C", ob));
Thread D = new Thread(new Player("D", ob));
A.setName("A");
B.setName("B");
C.setName("C");
D.setName("D");
A.start();
B.start();
C.start();
D.start();
try {
// Wait 5 seconds
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) { }
ob.writenum("DONE"); // cause the players to quit their threads.
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) { }
}
}
class Player implements Runnable {
num area; // Table where they play
String who;
public Player(String who, num area) {
this.area = area;
this.who = who;
}
public void run() {
while (area.writenum(who));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.