[1]首先,在您的發佈代碼中有幾個不好的練習/錯誤:
(1)鎖定對象最好是單身。你可以使用一個靜態字段對象或類本身(由於只有一個類在存儲器中)
Object _lock = new Object();
private static final Object _lock = new Object();
(2)將while(true) {...}
出同步塊的。在你的代碼中,如果第一個線程獲得鎖定,它將處理所有票據並且不會停止。 應該讓每個線程都嘗試在循環的每次迭代中獲得Lock。
(3)對於Thread.sleep(10)
,我想你的意思是線程正在做一些繁重的工作。但將這種代碼放入同步塊(或另一個名稱:關鍵區域)不是一個好習慣。因爲一次只有一個線程可以訪問同步塊。你的代碼行爲就像是一個單線程程序,因爲其他線程必須等到當前正在運行的線程完成其工作。
請參見下面的代碼:
public class ThreadDemo1 {
public static void main(String[] args) {
MultiThread tt = new MultiThread();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
}
}
public class MultiThread implements Runnable {
private static int tickets = 100;
private static final Object _lock = new Object();
public void run() {
System.out.println(Thread.currentThread().getName());
while (tickets > 0) {
try {
synchronized (_lock) {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + " is selling " + tickets--);
}
}
Thread.sleep(10);
} catch (Exception e) {
}
}
}
}
[2]第二,如果你只是想線程在採摘門票同步。嘗試使用Atomic*
類而不是同步塊,它是無鎖,並會帶來更好的性能。例如:
import java.util.concurrent.atomic.AtomicInteger;
public class MultiThreadAtomic implements Runnable {
private static AtomicInteger tickets = new AtomicInteger(100);
public void run() {
System.out.println(Thread.currentThread().getName());
int ticketsRemaining = 0;
while ((ticketsRemaining = tickets.getAndDecrement()) > 0) {
System.out.println(Thread.currentThread().getName() + " is selling " + ticketsRemaining);
try {
Thread.sleep(10);
}
catch(InterruptedException ie) {}
}
}
}
鎖必須是靜態 –
你有一些古怪的格式有...採用更標準的格式化會幫你寫更清晰的代碼,我們理解你的代碼。例如,你原來的帖子中遺漏了大括號,這完全不清楚。 – yshavit