Java 监视阻止操作
我正在尝试编写一个线程来监视阻塞操作需要多长时间。例如,我有一个如下的阻塞动作:Java 监视阻止操作,java,multithreading,race-condition,Java,Multithreading,Race Condition,我正在尝试编写一个线程来监视阻塞操作需要多长时间。例如,我有一个如下的阻塞动作: class BlockingThread extends Thread{ public volatile boolean success = false; public volatile long startedTime = 0; public void run(){ startedTime = System.currentTimeMillis(); succe
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
}
}
我想要另一个线程,如果阻塞操作花费的时间太长,它基本上会调用“timeout”函数:
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();
不能保证其中一个线程在另一个线程之前开始运行代码,因此我目前无法知道超时线程是否正确地测量了阻塞操作的时间。我假设答案与锁定和等待有关,但我无法理解。在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
}
}
}
}
我可以建议您使用类重写代码。 这个类有一个很好的方法
waittermination()
,我想这正是您所需要的
编辑:
这是您的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
doBlockingAction到底做什么?JavaAPI中的大多数阻塞操作都有允许设置超时的变体。使用超时变量是最准确的方法。我希望您指的是
class BlockingThread
和class MonitorThread
。有一种方法专门用于超时方法执行。这可能会有帮助。@Jeffrey哈哈,哎呀。感谢您的帮助。我不明白为什么您不能简单地执行while(blockingThread.startedTime==0 | | System.currentTimeMillis()-blockingThread.startedTime>TIMEOUT\u DURATION)
@AdrianShum,因为JVM可以随时在线程之间切换。因此startedTime可以设置为当前时间,然后在执行线程的下一行(阻塞操作行)之前,JVM开始运行一个新线程。或者至少,我是这样理解的。对不起,我不明白这是如何解决我的问题的。你能说得更具体些吗?