1

負荷の高いタスクを処理するスレッドアプリケーションがあり、外部フラグ情報に基づいてスレッドを強制的に停止したいと考えています。私は次のデザインを試しました、

public class HeavyTaskThread implements Runnable
{
   private boolean forceStop;

   public void run()
   {
     ..
     ..
     ..
     ..
   }
}

もう 1 つの事実は、メソッドに実装されたロジック フローを制御できないことrun()です。サードパーティのプログラムを呼び出すだけです。軽量の内部スレッド クラスとinterrupt()親スレッドでメソッドを呼び出すことを試みていましたが、これは機能しません。

おすすめのパターンを教えてください...

4

5 に答える 5

3

制御できないサードパーティ コードのアクティビティを処理するための推奨される方法は、別のプロセスとして起動することです。コードを強制的に停止する必要がある場合は、プロセスを強制終了します。親プロセスに影響を与えず、OS がクリーンアップの義務を負うため、スレッドを強制終了するよりもはるかにクリーンで安全です。

于 2012-08-21T05:17:48.120 に答える
0

これが最終的な分析です...スレッドを殺すためです。

  1. スレッドを使用してプログラム B の実行を制御します。ただし、関連するメソッドが非推奨 (停止/一時停止など) であるため、スレッドを介してプロセスを停止することは許可されません。

  2. ThreadGroup を使用して (メンバーとしてスレッドを 1 つだけ持つ)、グループで「destroy」を呼び出します。しかし、破棄操作が試行される前にすべてのスレッドを停止する必要があるため、これも同じ軌道に乗っています。

  3. ユーザー@Tudorが言及したように、ランタイムを介したプロセス/プロセスビルダーは、プロセス参照を取得し、destroy()、waitFor()などを呼び出すためのより良い方法のようです。

ここに私が試した正確なアウトラインコードがありますが、それは殺せませんでした。コメント行 while(isValid()) は私の別のJavaプログラムの呼び出しを表しています。



    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Date;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.CompletionService;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorCompletionService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.TimeUnit;

    class TaskWorker implements Callable {
        private final int number;

        public TaskWorker(int number) {
            this.number = number;
        }

        public Boolean call() throws InterruptedException {
            while (!Thread.currentThread().isInterrupted()) {
                myBusyFunction();
            }
            return true;
        }

        private boolean isValid() {
            return true;
        }

        private void myBusyFunction() {
            //while (isValid()) {
            System.out.println(number + ">....Working.....");
            //}
        }
    }

    public class Test {
        public static void main(final String[] args) {
            CompletionService cs = new ExecutorCompletionService(Executors.newFixedThreadPool(1));
            Collection tasks = new ArrayList(10);
            tasks.add(new TaskWorker(1));
            List> futures = new ArrayList>(tasks.size());
            try {
                for (Callable task : tasks) {
                    futures.add(cs.submit(task));
                }
                //----
                for (int t = 0; t  result = cs.poll(10, TimeUnit.SECONDS);
                    if (result == null) {
                        System.out.println(new Date() + ":Worker Timedout:");
                        //So lets cancel the first futures we find that havent completed
                        for (Future future : futures) {
                            System.out.println("Checking future");
                            if (future.isDone()) {
                                continue;
                            } else {
                                future.cancel(true);
                                System.out.println("Cancelled");
                                break;
                            }
                        }
                        continue;
                    } else {
                        try {
                            if (result.isDone() && !result.isCancelled() && result.get()) {
                                System.out.println(new Date() + ":Worker Completed:");
                            } else if (result.isDone() && !result.isCancelled() && !result.get()) {
                                System.out.println(new Date() + ":Worker Failed");
                            }
                        } catch (ExecutionException ee) {
                            ee.printStackTrace(System.out);
                        }
                    }
                }
            } catch (InterruptedException ie) {
            } finally {
                //Cancel by interrupting any existing tasks currently running in Executor Service
                for (Future f : futures) {
                    f.cancel(true);
                }
            }
            System.out.println(new Date() + ":Done");
        }
    }

于 2012-08-21T19:49:22.987 に答える
0

私はチューダーの答えに投票しますが、極端な場合、そしてあなたが必死になっている場合:

オプション A - 問題のコードを再構築します。

  • お気に入りの Java 逆コンパイラを使用して、問題のクラスを再作成します。

  • にチェックを追加Thread.currentThread().isInterrupted()runます。

  • コンパイルし、変更したクラスをクラスパスの元のライブラリの前に配置します。

  • 元の jar が署名されている場合は、関連する署名アーティファクトを削除する必要がある場合があります。

オプション B - 側面 J

  • runメソッドのソースを調べ、必要に応じてお気に入りの Java 逆コンパイラを使用します。

  • ステップインして停止するための、内側のループ内の適切なポイントを特定します。

  • コードでの例外処理を調べます。抜け穴はありますか?

  • コードの挿入: 必要に応じて例外をスローしたり、例外をキャッチしたりして、run.

于 2012-08-21T06:17:35.207 に答える