Javaのを教える姉妹校:手に負えないマルチスレッド

00起源、物語

「どのように影響する効果の種類ああ?」「ブラザー、Javaの」列を教えるために姉妹校「彼女の提案について非常に懸念し三明の設定」に。

「第一章よりも記事の景色、」一般的な「はるかに良いです。」

「これは弟の作成を受け入れるために、より多くの人々を示す良いニュースああ、である。」三明アップ得意。

「おそらく、ノー比較。」

「そこにはコントラストがありません?私は記事を書くために7ヶ月前にビット弟を見て、水は、ああ、本当に喜喜である。」三明は萌えを販売し、正直に言うと」、続けたが、読んでて喜んで読者が残っています、それは本当に信じられないです。」

「もしあなたが打撃をしたいですか?」

「彼らは、物品の高品質を見るので。ああ。私が意味する、兄と今の読者は本当にラッキー、しないでください」三明が大手を振っていき、彼女の真実を話しました。

マルチスレッド「準備三明君?」「以前よりもはるかに優れた、はいああ、私はまた、より多くの努力と同様に、今回はテーマがあるでしょう」

「早くも準備が整いました。兄は、あなたが答えを続け、私はそれを疑問視していきましょう。」三明すでに熱心。

01、弟、スレッドああは何ですか?

三明、あなたがああゆっくり話しを聞くために弟。

スレッドは単位プロセスであるため、スレッドを理解するには、まず、プロセスを理解しなければなりません。あなたは、私は同時に、このコンピュータは、この入力方法で入力すると、プロセスの多くを開いた、見るこの音楽プレーヤーで曲を聴く、ブラウザの役割を書きました。

オーディオを再生しながら歌詞をスクロールしながら、これらのプロセスは、音楽プレーヤーとして、同時にいくつかのことをやっていてもよいです。それは、同時に複数のスレッド(スレッド)を実行している可能性のあるプロセス内では、各スレッドは異なるタスクに責任がある、と言うことです。

プロセスは、少なくとも一つのスレッドを持つように、各プロセスので、少なくとも、一つのことを行います。少なくともメインスレッドと呼ばれるメイン方法があるだろう、Javaプログラムで。

同時に複数のスレッドを実行することができ、実装及び複数のプロセスが同じで、オペレーティング・システムによって決定されます。オペレーティング・システムは、複数のスレッド間で迅速に切り替えることができ、各スレッドが交互に実行されます。スイッチング時間が短いほど、プログラムの効率が高いです。

プロセスとスレッド間の関係は、簡単な言葉を使用することができ、「プロセスは、父と母、子供たちの多くとパイプスレッドです。」です

02、兄、なぜああマルチスレッドでしょうか?

第三姉、弟はコーヒーのカップに行くために、ゆっくりとあなたを伝える兄弟聞いてきます。

マルチスレッド、マルチタスクとして、途中で多くの利点を複雑。

まず、アプリケーションの応答時間を短縮。

あなたが複数のスレッドを使用しない場合コンピュータの場合、IOの読み取りと書き込み、ネットワーク通信は、比較的時間のかかる作業であり、その後、他の少ない時間のかかる作業も終了した後にこれらのタスクを実行するのを待つ必要があります。

第二に、マルチコアCPUを最大限に活用。

オペレーティングシステムは、スレッドの数は、CPUの数より大きくない場合、異なるCPU上の異なるスレッド上で実行されていることを保証することができます。しかし、スレッドの数は、CPUの数を超えた場合でも、オペレーティングシステムとスレッドプールは、それが、スレッド、同時実行可能な最大の利点を切り替えるプログラムのパフォーマンスを向上させるためにかかる時間を短縮するために、可能な最大を行います。

第三に、マルチプロセスと比較して、マルチスレッドは、より「効率的な」マルチタスクモードです。

異なるプロセスのために、彼らは別のデータ空間を持っている、データが「通信」モードの間で共有されなければなりません。そして、あなたは、スレッド、同じプロセス内のスレッド間で共有データスペースを必要としません。

2つのスレッドが同じオブジェクトにアクセスし、各スレッドがオブジェクトの状態を変更するためのメソッドを呼び出す場合はもちろん、それは新たな問題をもたらすでしょう。

何が問題でしょうか?のは、以下の実施例により例示されてみましょう。

public class Cmower {

    public static int count = 0;

    public static int getCount() {
        return count;
    }

    public static void addCount() {
        count++;
    }

    public static void main(String[] args) {
        ExecutorService executorService = new ThreadPoolExecutor(10, 1000, 60L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(10));

        for (int i = 0; i < 1000; i++) {
            Runnable r = new Runnable() {

                @Override
                public void run() {
                    Cmower.addCount();
                }
            };
            executorService.execute(r);
        }
        executorService.shutdown();
        System.out.println(Cmower.count);
    }

}

私たちは、スレッドプールを作成し、スレッドプールは、1000件のスレッドの実装によりループを可能にし、各呼び出しCmower.addCount()操作のカウント値に1を加え、スレッドが終了する1000の方法、コンソールの印刷カウント値。

その結果、それは何でしょうか?

998,997,998,996,996

しかし、ほとんど私たちが望むものを1000年に応答しません。

03、弟は、なぜその答えはまだ1000年ではないでしょうか?

三明ああ、コーヒーの強すぎるバブル。しかし、利点はより少しピックミーアップを集中しています。

プログラム動作では、データは計算後、その後、物理メモリへのデータ・キャッシュは、それらを更新し、CPUのキャッシュに物理メモリから計算をコピーする必要があります。

取るcount++ことを。スレッドが実行されると、この文は、物理的に最新の更新のキャッシュカウント値、CPUの命令実行回数がインクリメントされ、キャッシュにコピーし、その後、物理メモリのカウント値を読み始めますそれらのメモリ。

マルチコアCPUでは、各スレッドは異なるCPU上で実行される場合がありますので、高速走行での各スレッドは、キャッシュ専用されます。スレッドカウントがインクリメントされると仮定され、キャッシュスレッドB数の今回値がまだ0、1の値を加算した後のカウント動作です。最後の2つのスレッドが代わりに理想的な2の、物理メモリへの1の最新の値を更新します。

この変数は、彼らはしばしば保護する必要があり、共有変数と呼ばれる複数のスレッドによってアクセスされます。

04、弟、そして共有変数を保護する方法?

三明ああ、私は河口コーヒー彼らの精神を持ち上げます。

例えば、カウントが表示され、以下のように変更してもよいです。

public static AtomicInteger count = new AtomicInteger();

public static int getCount() {
    return count.get();
}

public static void addCount() {
    count.incrementAndGet();
}

アトミックオペレーション(即ち、操作または複数の、またはすべての操作を行い、プロセスが任意の因子の実行を中断されない、または実行しないように)サポートAtomicIntegerの代わりに、基本的なint型の。

単純な分析AtomicIntegerクラス、ソースコードが興味深い変数で見ることができますunsafe

private static final Unsafe unsafe = Unsafe.getUnsafe();

Unsafeこれは、1つは、安全でない、当てにならない特別なクラスの操作を行うことができるということです。AtomicInteger使用Unsafeアトミック操作方法をcompareAndSwapInt()もCASとして知られているデータを更新します。

public final native boolean compareAndSwapInt(Object o, long offset,
                                                int expected,
                                                int x);

CAS動作にOパラメータが(例えば、COUNT)オフセットパラメータは、メモリ位置で行われると予想パラメータが所望の値であり、パラメータxは、値を更新する必要があります。

一般的な同期方法は、アドレスオフセット値Aから読み出されますAからBへ、Bの後にオフセットCASのその値を計算して得られたいくつかの新しい値を実行します オフセットの値が同時に変更されていない場合は、CAS操作が成功しました。

、アルゴリズムは、操作を再計算することができます別のスレッドが変数を変更する場合は、CASがそれを検出し(失敗した)しますので、変数を変更するために他のスレッドを心配することなく、操作CASは「書き込みを - - リードモディファイ」を実行することができました。

AtomicIntegerSourceクラスには、変数があることは注目に値しますvalue

private volatile int value;

valueキーワードを使用しvolatile、視認性を確保するために-複数のスレッドが同じ変数にアクセスすると、スレッドはこの変数の値を変更し、他のスレッドはすぐに変更された値を見ることができます。

共有変数がされるとvolatile後で変更、他のスレッドが、読んで、新しい物理メモリーの値を読み取る行く必要がある場合、値が物理メモリに即座に更新されます修正されます。

されることなく、volatile共有変数があるため、これらの変数の不確実性、可視性を保証することはできません変更され、他のスレッドがまだ古い値であってもよいし、オリジナルを読んで、読むためにどのような時には、物理メモリに書き込まれます。

特に注目すべき点であるvolatileキーワード、変数の可視性のみを保証し、アトミック保証することはできません。

05、話を続けることにします

「それは最初にこのについて話した上で、私はより多く吸収することができない、!」「ブラザーは、」マルチスレッド三明の態度は非常に誠実です。

「月」。

「ブラザーは、私はあなたが大きな貢献を与えると言わ最後の時間を覚えて、どのように結果は?」三明は懸念して尋ねました。

「ああ、私は、言って恥ずかしいだけアップ絵文字2足の親指を収穫し、または思いやりに基づくものであってもよいと思います。私は怖がって提出、それを書くために最初に付着することはできません!」

「荒涼結末はあなたが実際にそれを再印刷する番号を持っていない?私はまだ300個の公共貢献・グループ番号の上にあると思います。」三明は非常に悲しいです。

「シリーズ・タイトルの」Javaを教えるために姉妹校は「右、少しの当事者であるかもしれません?」

「ブラザーは、書くために決定するので、自分を疑わない。三明は、少なくともこのスタイルああ言っています。」三明の真剣を聞いた後、私は優しい心と自己疑いの消えました。

 

おすすめ

転載: www.cnblogs.com/qing-gee/p/10982933.html