1

を実装するクラスがある場合、技術的には、複数のスレッドが同じインスタンスで同時にjava.lang.Runnable呼び出すのを止めるものはありません。例:runRunnable

Runnable r = new MyRunnable();

//start thread 1
new Thread(r).start();

//start thread 2
new Thread(r).start();

runメソッドが完全に「自己完結型」(つまり、プライベート インスタンス メンバーに依存しない)の場合、これは実際には問題になりません。スレッド間で共有される変数Runnableがないため、「破損した」内部状態になることは決してないからです。しかし、ほとんどの場合、で操作するプライベート インスタンス メンバーRunnable いくつかあるrunと思います。

例を使用すると、私のMyRunnableクラスにはプライベートmodeフィールドがあります。run主な目的は、 ( に設定modeすることによって) メソッドを完全に停止することですSTOPPEDが、他の用途もあります。

public static class MyRunnable implements Runnable
{
    enum Mode { RUNNING, PAUSED, STOPPED, FASTFORWARDING, REWINDING; }

    private volatile Mode mode;

    @Override
    public void run() 
    {
        mode = Mode.RUNNING;
        while (mode != Mode.STOPPED)
        {
            //do stuff. possibly other changes to the mode.
        }
    }

    public void setMode(Mode mode)
    {
        this.mode = mode;
    }

    public Mode getMode()
    {
        return mode;
    }
}

ご覧のとおり、 (前に示したように)の同じインスタンスに対して複数のスレッドを同時に実行すると、 への変更は、同時に実行されているスレッドにさまざまな方法で影響を与える可能性があります。たとえば、あるスレッドが を に設定すると、他のすべてのスレッドが に設定されたことを確認する前に、別のスレッドが を別のものに変更する可能性があります。これにより、スレッドが while ループを終了するのを簡単に防ぐことができます。MyRunnablemodemodeSTOPPEDmodeSTOPPED

Runnableでは、 「同時に使用できる」ように設計するにはどうすればよいでしょうか。それは可能ですか?それだけの価値はありませんか?私が使用できるC#のThreadStatic属性のようなものはありますか(このコンテキストでは完璧だと思います)?

4

5 に答える 5

9

MyRunnable複数の使用から保護するのではなく、このシナリオで your の複数のインスタンスを構築する方がはるかに一般的です。

//start thread 1
new Thread(new MyRunnable()).start();
//start thread 2
new Thread(new MyRunnable()).start();

複数のスレッドを機能させる全体的な目的は、優れた並列コンピューティングを実現することです。スレッドが共通のリソース (ワーク キューなど) をロックする必要がある場合はRunnable問題ありませんが、それらを「同時に使用できる」ように s を記述することは、当然のこととして行うべきではありません。そうする正当な理由があるはずです。

それは可能ですか?

確かにそれは可能です。スレッドは常にスレッド間でリソースを共有します。ただし、Mode mode変数の場合、これはRunnableクラスの複数のインスタンスで行う必要があります。

複数のスレッドが共通のコードを呼び出している場合、スレッドThreadLocalごとの情報を格納するために使用できるパターンの 1 つを検討できます。しかし、あなたの複数のインスタンス内にフィールドを格納するMyRunnableことは、.MyRunnablemodeThreadLocal

それだけの価値はありませんか?

これが原則として行われる場合、それは確かに価値がありません。繰り返しますが、スレッドをフォークすることの全体的なポイントは、複数のプロセッサを利用するためにスレッドを他のスレッドからできるだけ分離することです。

于 2012-05-22T15:14:12.017 に答える
1

スレッドセーフになるように他のメソッドまたはクラスを設計するのと同じ方法です。Runnable と本質的な違いはありません。

C# ThreadStatic はThreadLocalVariableと同等ですが、それが適切な解決策であるかどうかは誰にもわかりません。クラスにどのような動作をさせたいかを知る方法がないためです。

各スレッド実行に (状態に関して) Runnable の独立した実行を効果的に持たせたい場合は、異なるインスタンスを持つ方が理にかなっています (そしてはるかに簡単です)。

于 2012-05-22T15:20:16.323 に答える
0

Java での MP の経験が豊富であるとは言えませんので、一般的な使用法については説明しませんが、RunnableThreadのドキュメントを読んだ後では、Runnable はまさにその名前を意図しているように思えます。意味: 実行可能なオブジェクト。具体的には、ドキュメントでは、スレッドを実装したくないが同様の概念が必要な場合に Runnable を使用することについて言及しています。Runnable は、並列または並行アルゴリズムをカプセル化するクラスにとって理想的であると私は実際に考えています。確かに、Runnable を同時実行のために特別に設計すべきではない、または設計できないということを意味するものは何もありません。もちろん、それ自体 (タスクによって異なります) は、単一の SO 質問で対処できる以上のものです。

編集: 明確にする必要があります。Runnable 内に並列または並行アルゴリズムをカプセル化することについて言及しましたが、Runnable 内にタスクをカプセル化し、そのタスクに並列リソースを割り当てるかどうかを呼び出し元に決定させることも意味があることを伝えるつもりでした。たとえば、並行スレッドで呼び出すことによって。私のポイントは、ドキュメントが暗示しているように、(任意のコンテキストで) オブジェクトが実行されていることを想像できる場合、 Runnable が良い賭けになる可能性があるということです!

于 2012-05-22T15:21:16.600 に答える
0

OPの質問は、ランナブルがリソースを大量に消費する特定のシナリオにあると思いますが、これらのランナブルの再作成を回避する方法はありますか?

私の経験では、いつでも軽量の Runnables を作成して、重いリソース (巨大な配列など) を参照できます。複数のスレッドで同じ Runnable を呼び出すことは避けますが、スレッドごとに異なる Runnable を作成することは、私の意見ではより良い方法です。

于 2012-05-22T15:24:20.217 に答える
0

一般的に、それは価値がありません。

とにかく、新しいインスタンスを作成するコストがRunnable高すぎることはありません。そうである場合は、初期化にコストがかかる部分を除外する方法を検討し、それらがスレッドセーフであることを確認する必要があります。

もちろん、ThreadLocal変数を使用することもできます。これは全体として信じられないほど便利ですが、このシナリオではおそらくそうではありません。

于 2012-05-22T15:13:59.167 に答える