2014-07-12 52 views
0

當線程訪問鎖定對象時,有什麼辦法可以運行一段代碼嗎?當線程被內部鎖定阻塞時執行代碼

public class Student implements Runnable { 

private String name; 
private Workshop w; 

public Student(String name,Workshop workshop) { 
    this.name = name; 
    this.w=workshop; 
} 

@Override 
public void run() { 

    this.w.getReady(); 
    this.w.file(this.name); 
    this.w.cut(this.name); 
    this.w.punch(this.name); //Synchronized Method 

    if(Thread.currentThread().getState()==Thread.State.BLOCKED) 
     System.out.println(this.name+" is waiting in queue"); 

    System.out.println(this.name+" has finished and is going home"); 
} 

} 

這是一個模擬車間的場景,每個學生都必須對金屬工件進行歸檔,切割和打孔。
由於衝壓輪流轉,我已經宣佈它是同步的,因爲每個學生(線程)將不得不等待輪到他們衝。
所有我想知道的是,如果有一些內置的方法或一種方法來編寫一個方法,當一個線程被阻塞並且正在等待內部鎖被解鎖時被執行。


public void onBlock() { 
    System.out.println(this.name+" is waiting in queue"); 
    ... 
} 
+0

據我所知,不 - 如果你的線程在等待某件事情,它不能停止並執行其他事情(沒有一些*真正討厭的解決方法)。我不完全確定,但是,所以不回答... – awksp

回答

1

對於由​​保護對象顯示器,沒有,它要麼成功鎖定或阻塞無限期地等待鎖。

如果您使用的是ReentrantLock或類似的,你有更多的選擇:

  1. 您可以無限期地等待,就像對象監視器,通過調用lock
  2. 您可以用超時值調用tryLock來等待有限的時間。
  3. 如果通過調用tryLock而不帶參數鎖定不可用,您可以立即返回。
+0

嗯,我知道它被阻止,我將不得不等待它被解鎖,但我的問題是如何打印像**這樣的東西線程正在等待鎖被刪除「**當另一個線程加載鎖定的對象時。 –

+0

對象監視器不允許您查看哪個線程(如果有)擁有鎖定。 'ReentrantLock'確實有一個可以調用的'getOwner'方法。 –

+0

如果你想知道哪些線程被阻塞,你可以運行'jstack'。但是,這不會在Java程序中運行;這是一個外部過程。 –

1

一個不雅的解決方法可能如下所示:

// In the Workshop class. 
private static final AtomicReference<Boolean> IN_USE = new AtomicReference<>(false); 

private void getInLineToPunch(String name) { 
    while(!IN_USE.compareAndSet(false, true)) { 
    System.out.println(name + " is waiting in line to punch."); 
    try { 
     Thread.sleep(SOME_INTERVAL); 
    } catch(InterruptedException ex) { 
     // This will probably not occur unless you interrupt this thread on purpose. 
     ex.printStackTrace(); 
    } 
    } 

    // At this point, no one is using the punch. 
    System.out.println(name + " will now use the punch."); 
    punch(); 

    // I am done with the punch. 
    System.out.println(name + " is done with the punch."); 
    IN_USE.set(false); 
} 

對於這種方法,有必要使用AtomicReference避免競爭條件。

也許另一種方法是使用監視線程來定期輪詢每個線程並宣佈它被阻止。

相關問題