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

スレッドの 1 つが実際に他のスレッドの前にコードの実行を開始するという保証はありません。したがって、現在、タイムアウト スレッドが実際にブロッキング アクションの時間を正しく測定しているかどうかを知る方法がありません。答えはロックとwaitイングに関係していると思いますが、わかりません。

4

3 に答える 3

4

クラスを使用してコードを書き直すことをお勧めしますjava.util.concurrent.ThreadPoolExecutor。このクラスには素晴らしいメソッドawaitTermination()があります。私が思うに、まさにあなたが必要としているものです。

編集:

これが、10秒実行しているBlockingThreadと、5秒待機しているMonitorです。

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

doBlockingAction は正確には何をしますか? Java API のほとんどのブロッキング アクションには、タイムアウトを設定できるバリアントがあります。そのタイムアウトしたバリアントを使用するのが最も正確な方法です。

于 2012-08-31T08:58:38.317 に答える
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 に答える