0

特定のポートを介して一連のファイルを複数のコンピューターに送信する必要があります。実際には、ファイルを送信するメソッドが呼び出されるたびに、宛先データ (アドレスとポート) が計算されます。したがって、メソッド呼び出しごとにスレッドを作成するループを使用し、BindException の try-catch ステートメントでメソッド呼び出しを囲み、既に使用されているポートを使用しようとするプログラムの状況を処理します (宛先アドレスが異なると、同じポートを介してメッセージを受信する) スレッドに、数秒待ってから再起動して再試行し、例外がスローされなくなる (配送が正常に実行される) まで試行を続けるように指示します。理由はわかりませんでした (最初に見たときは推測できましたが)、Netbeans は、ループ内で Thread オブジェクトをスリープ状態にすることは最善の選択ではないことを警告しました。これは別のスタックオーバーフローの投稿へのリンクで、とても面白そうでした (私はThreadPoolExecutor クラスについて聞いたことがありませんでした)。プログラムを改善するために、そのリンクと API の両方を読んでいますが、それを自分のプログラムにどのように適用すればよいか、まだよくわかりません。誰でもこれについて手を差し伸べてもらえますか?

編集:重要なコード:

        for (Iterator<String> it = ConnectionsPanel.list.getSelectedValuesList().iterator(); it.hasNext();) {
        final String x = it.next();
        new Thread() {

            @Override
            public void run() {
                ConnectionsPanel.singleAddVideos(x);
            }
        }.start();
    }

    private static void singleAddVideos(String connName) {
    String newVideosInfo = "";

    for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
        newVideosInfo = newVideosInfo.concat(it.next().toString());
    }

    try {
        MassiveDesktopClient.sendMessage("hi", connName);
        if (MassiveDesktopClient.receiveMessage(connName).matches("hello")) {
            MassiveDesktopClient.sendMessage(newVideosInfo, connName);
        }
    } catch (BindException ex) {
        MassiveDesktopClient.println("Attempted to use a port which is already being used. Waiting and retrying...", new Exception().getStackTrace()[0].getLineNumber());
        try {
            Thread.sleep(MassiveDesktopClient.PORT_BUSY_DELAY_SECONDS * 1000);
        } catch (InterruptedException ex1) {
            JOptionPane.showMessageDialog(null, ex1.toString(), "Error", JOptionPane.ERROR_MESSAGE);
        }
        ConnectionsPanel.singleAddVideos(connName);
        return;
    }

    for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
        try {
            MassiveDesktopClient.sendFile(it.next().getAttribute("name"), connName);
        } catch (BindException ex) {
            MassiveDesktopClient.println("Attempted to use a port which is already being used. Waiting and retrying...", new Exception().getStackTrace()[0].getLineNumber());
            try {
                Thread.sleep(MassiveDesktopClient.PORT_BUSY_DELAY_SECONDS * 1000);
            } catch (InterruptedException ex1) {
                JOptionPane.showMessageDialog(null, ex1.toString(), "Error", JOptionPane.ERROR_MESSAGE);
            }
            ConnectionsPanel.singleAddVideos(connName);
            return;
        }
    }
}
4

1 に答える 1

1

あなたの質問はあまり明確ではありません-タスクが成功するまで(BindExceptionなしで)再実行したいことを理解しています。それを行うには、次のことができます。

  • 例外をキャッチせずにコードを実行してみてください
  • 未来からの例外をキャプチャする
  • 失敗した場合は少し後でタスクを再スケジュールする

単純化されたコードは次のようになります - エラーメッセージを追加し、必要に応じて改良してください:

public static void main(String[] args) throws Exception {
    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(corePoolSize);
    final String x = "video";
    Callable<Void> yourTask = new Callable<Void>() {
        @Override
        public Void call() throws BindException {
            ConnectionsPanel.singleAddVideos(x);
            return null;
        }
    };
    Future f = scheduler.submit(yourTask);
    boolean added = false; //it will retry until success
                           //you might use an int instead to retry
                           //n times only and avoid the risk of infinite loop
    while (!added) {
        try {
            f.get();
            added = true; //added set to true if no exception caught
        } catch (ExecutionException e) {
            if (e.getCause() instanceof BindException) {
                scheduler.schedule(yourTask, 3, TimeUnit.SECONDS); //reschedule in 3 seconds
            } else {
                //another exception was thrown => handle it
            }
        }
    }
}

public static class ConnectionsPanel {

    private static void singleAddVideos(String connName) throws BindException {
        String newVideosInfo = "";

        for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
            newVideosInfo = newVideosInfo.concat(it.next().toString());
        }

        MassiveDesktopClient.sendMessage("hi", connName);
        if (MassiveDesktopClient.receiveMessage(connName).matches("hello")) {
            MassiveDesktopClient.sendMessage(newVideosInfo, connName);
        }

        for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
            MassiveDesktopClient.sendFile(it.next().getAttribute("name"), connName);
        }
    }
}
于 2012-08-17T09:17:19.697 に答える