0

異なるスレッドで実行されている 2 つの Java クラスがあります。1 つのクラスがインターネットに接続し、もう 1 つのクラスが接続ステータスを監視します。サーバーの応答の読み取り中に接続を作成するクラスが遅延する場合にIOExceptionをスローしたいと同時に、サーバーから応答が読み取られている場合に例外をスローしたくありません。

私はこのコードを思いつきました。

私の問題は、メインクラスである NetworkConnector クラスによってキャッチされるクラス NetworkMonitor で IOException をスローしたいことです。ただし、コンパイラはキャッチされていない例外について不平を言います。

  public class NetworkConnector{
  //method that connects to the server to send or read data.
  public String sendData(String url ,String data){
     try{

        //start the monitor before we read the serverResponse
        new NetworkMonitor().startMonitor();

        int read ;
        while ((read = inputStream.read()) != -1) {
           //read data.
           sb.append((char) read);

           //monitor if we are reading from Server if not reading count 10 to 0 and throw IoException. 
           new NetworkMonitor().resetCounter();
        }

     } catch(IOException ex){
        //all IOException should be caught here.
     }

  }

}

// ネットワーク アクティビティが発生しているかどうかを監視するクラス。

  public class NetworkMonitor implements Runnable {

  private final int WAITTIME =10;
  private int counter = WAITTIME;


  public void run(){
     try{

        while(counter > 0){
           //waiting here
           counter--; //decrement counter. 
           Thread.sleep(1000);     
        }

        //when counter is at zero throw iOexception 
        throw new IOException("Failed to get server Response");

     } catch(InterruptedException e){
        System.out.println(e.getMessage());
     } catch(IOException e){
        //i want to throw the IOEception here since the exception should 
        //be caught by the networkConnector class not the monitor class but the compiler complains.
        // unreported exception java.io.IOException; must be caught or declared to be thrown
        throw new IOException(e.getMessage());

        //throwing another exception type is okay ===>why cant we throw the same type of exception we caught.
         throw new IllegalArgumentException(e.getMessage()); 
     }


  }

  //reset the counter if called.
  public void resetCounter(){
     counter = WAITTIME;
  }

  public void startMonitor(){
     Thread t = new Thread(this);
     t.start();
  }

}

4

4 に答える 4

2

もっと基本的な問題があります

  • あるスレッドでスローされた例外を別のスレッドに渡す必要があります。これを行うには、ExecutorServiceとFutureを使用できます。
  • タイムアウトを実装するには、ScheduledExecutorServiceを使用できます。これにより、遅延してキャンセル可能なタスクをスケジュールできます。
  • 1つのスレッドで例外がスローされても、ブロックされている読み取りのブロックは解除されません。ブロックを解除するには接続を閉じる必要があります。これにより、IOExceptionが発生します。
  • これらを配置したら、Runnableの代わりにCallableを使用して、チェックされた例外をスローできます。

1秒間寝る代わりに10回。あなたはただ10秒間眠ることができます。

于 2012-12-11T09:28:07.777 に答える
0

2 つのスレッド間で何らかの通信を実現しようとしていると思います。例外は、そのためのエレガントなソリューションではありません。volatileblocking queuesなどexecutor serviceとのより良い通信方法に対応するようにコードを変更することをお勧めしますfuture。これを実現する方法の 1 つを以下に示します。

LinkedBlockingQueueこれら 2 つのスレッドを次のようにフォークする場所から、メイン クラスに を作成します。

LinkedBlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<Integer>(
        1);

このキューを両方のスレッドに渡します。volatileネットワーク モニター クラスにメンバーを作成します。

volatile boolean isAllowed = true;

NetworkConnectorasの while 条件を変更する

while ((read = inputStream.read()) != -1 && networkMonitor.isAllowed()) { 

NetworkMonitor's runメソッドで while 条件を次のように変更します。

while(isAllowed) {
Integer i = blockingQueue.poll(10, TimeUnit.SECONDS);
if(i==null) 
  isAllowed = false;
}

これを追加しNetworkConnector's while loopた後の内部:append

blockingQueue.add(1);

基本的に、キューに整数を追加します。モニター スレッドが null 以外の整数を取得するとすぐに、最大 10 秒間待機します。コネクタ スレッドは整数をキューに入れるのに 10 秒かかります。そうでない場合は while ループが壊れます。ループから抜けたら、必要なことは何でもしてください。

私はこれを実行していません。これは最初の考えに基づく単なる例です。お役に立てれば。

于 2012-12-12T10:30:08.847 に答える
0

基本設計に欠陥があります。例外は、スレッド境界を越えて自動的に伝播しません。

やろうとしていることを行うには、おそらく非ブロッキング I/O を使用することを検討する必要があります。

于 2012-12-11T09:25:13.517 に答える
-1

run()からオーバーライドされたメソッドですRunnable。runnable インターフェースにはチェック例外の定義がないため、そこからチェック例外を投げることができませんでした。RuntimeExceptionしかし、その代わりに投げることができます。

于 2012-12-11T09:29:14.753 に答える