当线程被内部锁定阻塞时执行代码

时间:2014-07-12 03:06:59

标签: java multithreading synchronize

当线程访问锁定的对象时,有没有办法运行一段代码?

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");
}

}

这是一个Workshop场景的模拟,每个学生都必须对金属工件进行归档,切割和打孔 由于打击轮流,我已将其声明为同步,因为每个学生(线程)都必须等待轮到他们。 所有我想知道的是,如果有一些内置方法或一种方法来编写一个方法,当一个线程被阻塞并等待内部锁被解锁时执行该方法。

示例

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

2 个答案:

答案 0 :(得分:1)

对于受synchronized保护的对象监视器,否则它会成功锁定或无限期地阻塞等待锁定。

如果您使用的是ReentrantLock等,则可以选择更多选项:

  1. 您可以通过调用lock来无限期地等待,就像对象监视器一样。
  2. 您可以通过使用超时值调用tryLock来等待有限的时间。
  3. 如果锁定不可用,您可以通过不带参数调用tryLock来立即返回。

答案 1 :(得分: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来避免竞争条件。

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