我有兩種方法,request()
和release()
,每次訪問request()
直到它調用release()
必須採取控制線程,這意味着沒有其他線程將進入請求方法,直到當前線程還沒有結束。 我需要用java監視器和信號量來實現這個行爲。 這是類的線程:採用Java監視器代替信號燈
public class Process implements Runnable
{
private Thread thread;
private final int ID;
private Resource g;
private final int MIN = 1000, MAX = 5000;
private void delay()
{
try
{
Thread.sleep((int) Math.random() * (MAX - MIN) + MIN);
} catch(InterruptedException ex){}
}
public Process(int ID, Resource g)
{
this.thread = new Thread(this, "P#" + ID);
this.ID = ID;
this.g = g;
}
public void run()
{
while(true)
{
g.request(ID);
delay();
g.release();
delay();
}
}// run
public void start()
{
this.thread.start();
}
}
使用信號燈可以很容易地實現這一行爲,我走在request()
方法互斥鎖,並在release()
方法釋放:
public class ResourceS implements Resource
{
private Semaphore mutex = new Semaphore(1);
public void request(int ID)
{
try
{
mutex.acquire();
} catch (InterruptedException e){}
System.out.println(Thread.currentThread().getName() + " enter");
}
public void release()
{
System.out.println(Thread.currentThread().getName() + " exit");
mutex.release();
}
}
在主我推出五線,這裏是輸出:
P#0 enter
P#0 exit
P#1 enter
P#1 exit
P#2 enter
P#2 exit
P#3 enter
P#3 exit
P#4 enter
P#4 exit
P#0 enter
P#0 exit
P#1 enter
P#1 exit
P#2 enter
P#2 exit
P#3 enter
正如你可以看到它是正確的,因爲每個threa d只有在另一個人退出時才進入。 使用顯示器有一個問題,這裏是代碼:
public class ResourceMonitor implements Resource
{
private Object lock = new Object();
private boolean oneInside = false;
public void request(int ID)
{
synchronized (lock)
{
while(oneInside)
{
try { lock.wait(); } catch(InterruptedException e){}
}
System.out.println(Thread.currentThread().getName() + " enter");
oneInside = true;
}
}
public void release()
{
synchronized(lock)
{
if (oneInside)
{
lock.notifyAll();
oneInside = false;
}
System.out.println(Thread.currentThread().getName() + " exit");
}
}
}
這是使用顯示器的輸出。
P#0 enter
P#0 exit
P#4 enter
P#4 exit
P#0 enter
P#0 exit
P#4 enter
P#4 exit
P#0 enter
P#0 exit
P#4 enter
P#4 exit
只有兩個線程進入和退出,而不是有時的P#4
是P#1
。你知道發生了什麼,以及如何獲得使用信號量的相同輸出?
這裏是主要的,誰想要測試它的代碼:
public static void main(String args[])
{
Resource g = new ResourceS();
Process p0 = new Process(0, g);
Process p1 = new Process(1, g);
Process p2 = new Process(2, g);
Process p3 = new Process(3, g);
Process p4 = new Process(4, g);
p0.start();
p1.start();
p2.start();
p3.start();
p4.start();
}
您可以使用調試器來查看其他線程正在做什麼嗎? (在Eclipse中,我將在調試器中啓動程序,然後等待幾次迭代以確保線程實際上被卡住,然後暫停程序並分別查看每個線程) – immibis
「synchronized」關鍵字未實現監控。可悲的是。 – EJP
@immibis使用調試器,代碼按預期工作,也許代碼正常運行時會出現某種飢餓現象。可能是隊列中的所有線程之間只有兩個線程可以訪問臨界區。 – AR89