4

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

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();

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

4

3 回答 3

4

我可以建议您使用 class 重写您的代码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
于 2012-08-31T07:16:54.540 回答
0

在blockingThread.startingTime 初始化之前,您可能只需要循环几次。

class MonitorThread extends Thread{

    public void run(){
        boolean weWantToKeepRunning = true;

        // here is your new event loop
        while(weWantToKeepRunning){

            if (blockingThread.startedTime != 0) && (System.currentTimeMillis() - blockingThread.startedTime > TIMEOUT_DURATION)&& (!blockingThread.success){

                listener.timeout();   // too long
                weWantToKeepRunning = false;  // quit this loop

            }
        }
    }
}
于 2012-08-31T01:55:10.707 回答
0

doBlockingAction 到底是做什么的?Java API 中的大多数阻塞操作都有允许设置超时的变体。使用该超时变体是最准确的方法。

于 2012-08-31T08:58:38.317 回答