监控阻止操作

时间:2012-08-31 00:38:44

标签: java multithreading race-condition

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

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有关,但我无法弄明白。

3 个答案:

答案 0 :(得分:4)

我可以建议您使用类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

答案 1 :(得分: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

            }
        }
    }
}

答案 2 :(得分:0)

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