我正在尝试编写一个线程来监视阻塞操作需要多长时间。例如,我有一个类似的阻止动作:

class BlockingThread extends Thread{

    public volatile boolean success = false;
    public volatile long startedTime = 0;

    public void run(){

      startedTime = System.currentTimeMillis();
      success = doBlockingAction(); //no idea how long this action will take
    }

}

我想拥有另一个线程,如果阻塞操作花费的时间太长,它将基本上调用“超时”功能:
class MonitorThread extends Thread{

    public void run(){
      while(System.currentTimeMillis() - blockingThread.startedTime > TIMEOUT_DURATION)
      {
         ..keep waiting until the time runs out..
      }

      if(!blockingThread.success){
         listener.timeout();
         //Took too long.
      }
    }

}

我在测量MonitorThread中的时间时,无法理解如何确保BlockingThread实际上当前处于阻塞操作中。

如果我做这样的事情,
Thread blockingThread = new BlockingThread();
blockingThread.start();
Thread monitorThread = new MonitorThread();
monitorThread.start();

无法保证其中一个线程实际上先于另一个线程开始运行代码,因此,我目前无法知道我的超时线程是否实际上在正确测量阻塞操作的时间。我认为答案与锁定和wait编码有关,但我无法弄清楚。

最佳答案

我可以建议您使用 java.util.concurrent.ThreadPoolExecutor 类重写代码。
该类具有不错的方法awaitTermination(),我想正是您需要的方法。

编辑:

这是您的BlockingThread,运行10秒,而Monitor,等待5秒:

package sample.threadexecutor;

import java.text.SimpleDateFormat;
import java.util.Date;

public class BlockingThread implements Runnable{

    public boolean succsess = false;
    @Override
    public void run() {
        SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss.SSS");
        System.out.println(df.format(new Date())  + " start");
        try {
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            System.out.println(df.format(new Date())  + " interrupted");
            succsess = false;
            return;
        }
        System.out.println(df.format(new Date())  + " end");
        succsess = true;
    }
}

和执行器的主要功能:
package sample.threadexecutor;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class main {

    public static void main(String[] args) {
        SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss.SSS");
        ExecutorService service= Executors.newSingleThreadExecutor();
        service.submit(new BlockingThread());
        try {
            service.shutdown();
            if(service.awaitTermination(5, TimeUnit.SECONDS)){
                System.out.println(df.format(new Date())  + " execution completed");
            }else{
                System.out.println(df.format(new Date())  + " execution timeout");
            }
        } catch (InterruptedException e) {
            System.out.println(df.format(new Date())  + " monitoring interrupted");
        }

    }
}

和输出:
22:28:37.005 start
22:28:42.006 execution timeout
22:28:47.006 end

如果我们将超时设置为20秒,则输出:
22:30:20.210 start
22:30:30.213 end
22:30:30.214 execution completed

07-24 18:31