7

まだ頭を糸に巻き付けるのに問題があります。可能な限り簡単な方法でこれを実行しようとしています。スレッドはすべて、Runnableクラスから継承したrunメソッドを持っている必要があることを知っていますが、追加のメソッドも持つことができますよね?

その理由は、いくつかのプライベート変数とrunメソッドを持つスレッドがあるからです。それはrun関数を呼び出します、そしてそれが終わったら、私はまったく同じrunメソッドでスレッドを再利用したいと思います。変数が異なるだけで、まったく同じことを行います。したがって、setArrayメソッド(スレッドにはプライベートバイト配列が含まれています)のようなものを追加して、この新しい配列を使用してrunを再度呼び出すことができますか、それとも許可されていません。簡単に言えば、

Thread thread = new MyThread();
thread.start();

// Check if the thread has finished in a non-blocking way
if (thread.isAlive() == false) {
    thread.setArray(newArray)
    thread.start();
}

基本的に私は固定数のスレッドしか持っておらず、最初のスレッドの実行が完了したら、パラメーターを少し変更して再度実行したいと思います。私は彼らが死ぬことを望んでいません、それはjoinがすることのようです。

特定の問題については、4つのスレッドがあり、それぞれがより大きなバイト配列の設定されたサイズのブロックを提供します。各スレッドはその配列をDeflaterで圧縮し、その結果を同期を処理するマネージャーオブジェクトに渡します。最初のスレッド(配列の最初の部分を取得したスレッドのように、最初に終了したスレッドではない)が完了すると、スレッドに割り当てられていない次のブロックに移動します。

私はスレッドプールがオプションであることを知っていますが、それは少しやり過ぎのようです、そして私は本当にそれらを理解していません(私はまだ通常のスレッドだけで問題を抱えています)。

4

4 に答える 4

15

まず、標準Threadクラスを使用して(サブクラス化しないでください!)、アプリケーションコードをを実装するクラスに配置するのが最善Runnableです。これにより、スレッドの管理の問題からアプリケーションロジックを簡単に分離できます。

次に、Threadオブジェクトがメソッドを1回だけ呼び出すことを理解する必要がありますrun。メソッドが戻った後run(または例外で終了した後)、Threadオブジェクトは無効になり、元に戻すことはできません。

したがって、インスタンスを「再利用」する場合は、メソッドが(どういうわけか)次の処理が行われるのを待つループにThreadなるように調整する必要があります。runそして、あなたがそれを知る前に、あなたはスレッドプールを実装しています。

スレッドプールに代わる別の(より「現代的な」)代替手段があります。インスタンスを作成しExecutorService、メソッドを使用しsubmit()てインスタンスを送信しRunnableて実行します。インターフェイスjavadocには、プライベートスレッドプールでエグゼキュータサービスインスタンスを使用する良い使用例があります。必要に応じて、インスタンスを再利用できRunnableますが、通常は、毎回新しいインスタンスを作成する方が簡単(かつ安全)です。

于 2012-10-28T05:42:57.737 に答える
1

Runnableを実装するコード用に別のクラスを作成します。毎回新しいThreadオブジェクトを作成する必要がありますが、単一のRunnableオブジェクトを使用してこれらを作成します。runメソッドは、各スレッドで再利用されます。

于 2012-10-28T05:26:01.160 に答える
1

スレッドは常に1回だけ開始し、1回だけ実行してから、1回だけ終了します。したがって、提案した方法でスレッドでstart()を複数回呼び出すことはできません。

したがって、いずれにせよ、次のいずれかを行う必要があります。

  • run()メソッド内で、さまざまなパラメーターのセットを使用して各メソッド呼び出しを実行する単一のスレッドを用意します。
  • 「実行」ごとに新しいスレッドを開始します(実際に実行したいことへのメソッド呼び出し)。

どちらの実装がより適切かは、正確なアプリケーションによって少し異なります。ただし、一般に、スレッドを他のサブタスクと並行して実行されるサブタスクと考えると便利です。したがって、一般的に:

  • 互いに並行して実行する理由がない一連の独立した「実行」がある場合は、単一のThread.run()メソッド内でこれらの実行が次々に実行されるように調整します。
  • 互いに並行して実行することもできる一連のタスクがある場合は、それぞれを別々のスレッドに配置します。

スレッドプールは通常、任意の時点で任意のタスクを実行でき、そのようなタスクを並行して実行できる場合に使用されます。たとえば、一般的なサーバーでは。Webサーバーが、さまざまなクライアントからのページの要求を任意の時点で受信するとします。各要求は任意の時点で発生する可能性があり、あるクライアントからのページの要求は、別のクライアントからの要求から完全に独立しています。原則として、どのリクエストがどのリクエストと並行して実行されるかは関係ありません。ただし、マシンにCPUの数などのリソースの制約がある場合を除きます。このタイプのケースでは、「任意のスレッドで任意のタスクを実行し、並列で実行されるXタスクの制限まで」を効果的に実行する場合は、通常、スレッドプールを使用します。

于 2012-10-28T05:38:30.640 に答える
-3

スレッドは基本的に、実行する状態とメソッドを持つ単なるオブジェクトです。スレッドの例を次に示します。

public class ThreadWithState implements Runnable {

  private Object state;

  public ThreadWithState(Object state) {
    this.state = state;
  }

  public void run() {
    // Do something with state
  }
}

スレッドは通常、並列で実行されます。そうでない場合、マルチスレッドのポイント全体が失われます。したがって、次のDriverクラスに示されているように、スレッドのプールを使用して実行しようとします。

public class Driver {

  public static void main(String[] args) {
    ThreadWithState thread = new ThreadWithState(null);
    ThreadWithState thread2 = new ThreadWithState(new Object());
    ThreadWithState thread3 = new ThreadWithState(new Object());
    ThreadWithState thread4 = new ThreadWithState(new Object());

    ExecutorService service = Executors.newFixedThreadPool(4);
    service.submit(thread);
    service.submit(thread2);
    service.submit(thread3);
    service.submit(thread4);
    service.shutdown();
  }
}
于 2012-10-28T05:42:17.427 に答える