2014-07-12 53 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避免竞争条件。

也许另一种方法是使用监视线程来定期轮询每个线程并宣布它被阻止。

相关问题