マルチスレッドプログラミング(1)

1.プロセスとスレッド

  典型的には、ジョブは、ブラウザを開くように、プロセス(処理)であるブラウザの起動プロセスである、Wordを開くために、プロセスをWordを開始しました。プロセスは、Wordなどの多くのことを、実行する必要があり、時間のほとんどは、チェック、印刷や他のものを綴る、タイピングを同時に行うことができます。プロセスの中で、同時にやっているより多くのもの、あなたが複数の「サブタスク」を実行する必要があり、我々はプロセスでこれらの「サブタスク」を入れてスレッド(スレッド)と呼ばれています。つまり、プロセスは、少なくとも一つのねじ山を有し、少なくとも1つのプロセスのプログラム

  我々 UNIVERSITYオペレーティングシステム彼らは両方のことを知って、プロセスがリソース割り当ての基本単位であり、スレッドは実行およびスケジューリングの基本単位である、自身のスレッドは、そのプロセスからリソース、リソースを持っていません。すなわち、実行プロセスの間に、ある他のプロセスに互いから分離し、従ってに、独自のメモリ空間を有しているとの間の通信経路、新しい経路を開く必要があり、このような共通の通信、メッセージキュー、セマフォなどソケットのようなダクトを、一方、プロセスは3つの大きな有する-プロセス制御ブロック(PCB)を、大きなオーバヘッドにつながるデータセグメント、コードセグメントは、プロセス間を有することになります。スイッチング速度は、スレッド・プロセスよりもはるかに高速であるように、以下に記載されるように、互いの間とすることができるアプリケーション・プロセスおよびスレッドをスレッド間の共有メモリ領域通信ので、なぜなら糸の小さいサイズのため、大きく、プログラムの効率を向上させることができ、スレッドはそして、関係のプロセス(から撮影された画像はほとんど知られています)。

  ユーザスレッドとスレッドガード:2つのスレッドに分割されます。デーモンスレッドは、プログラムは、ガベージコレクションのスレッドとしてスレッドを実行している背景にユニバーサルサービスの提供を指し、非常に有能なの守護者であり、このスレッドは、プログラムの不可欠な部分に属していません。デーモンスレッドがユーザスレッドがすべての上に実行していると、ユーザスレッドにサービスを提供するために使用され、プログラムが終了し、スレッドも終了しますの守護者。

  マルチスレッドに入る前に、あなたは、スレッドのいくつかの状態を見てみることができます。

  • 1. 新しい(NEW) 新しいスレッドオブジェクトを作成します。
  • 2. (RUNNABLEまたはREADY)準備:スレッドが競争の中でCPUを使用する権利を参加しています。
  • 3. ファイル名を指定して実行(RUNNING):CPUを使用する権利にスレッドを取り、実行されます。
  • 4. ブロックされたが(ブロック):スレッドがCPUを使用する権利を放棄するためにいくつかの理由でブロックされて一時的に実行を停止します。条件は、CPUの使用権を競合する、バックレディ状態にスレッド(例えば、タイムアウト待ち、ウェイクアップのように)満たされるまで。
  • 5. (WAITING)待ち:無期限に待つオブジェクトをロック、または状態の終わりに別のスレッドを待つスレッド。
  • 6. タイミング待ち(TIME_WAITING) 中断し、タイムアップしない限り、スレッドの一定期間内のオブジェクトを待つ「ロック」、又は活性睡眠、またはスレッドの終了を待つことにより、直ちに準備完了状態に戻り、中断されメソッドは例外をスローします。
  • 7. 終了(終端):終了するそのスレッド(スレッドのコードが終了する)と、異常な又は強制外界によって中断実行。

以下に示すように、特定の変換の状態遷移:

2. Threadクラスと、Runnableインタフェース

  これは、スレッドクラスThreadクラスの継承、実際のrunメソッドによって実現することができ、一般的に使用されるAPIは、次のように:

  方法について説明します
開始() 準備完了状態から新しい状態遷移は、競争の中でCPUを使用する権利を参加し始めました。
実行() ダイレクトコールRunnableオブジェクトのrunメソッドそのCPUを使用する権利への直接アクセス
割り込み() 割り込みスレッド。有するプログラムコードで一方(!Thread.interrupted()){..}使用。
isDaemon() 現在のスレッドがデーモンスレッドであるかどうかを決定します。
setdaemon(ブール真) デーモンスレッドとして現在のスレッドを設定し、()の開始を呼び出した後に有効にする必要があります。
setPriorityを(int型の優先順位) スレッドの優先順位を変更します。
割り込み() 割り込みスレッド。
生きている() このスレッドがアクティブであるかどうか。
(長いミリ秒)に参加 ミリ秒(ミリ秒)の最大にこのスレッドを待ちます。
Thread.yield() 現在実行中のスレッドオブジェクトを一時停止(レディ状態に、現在のスレッドのCPUを聞かせ)、および他のスレッドを実行します。
Thread.currentThread() それは、現在実行中のスレッドオブジェクトへの参照を返します。
Thread.sleep(長いミリ秒) 指定されたミリ秒数(中断)、この主題とシステムタイマーとスケジューラ精度の精度にスリープ状態に現在実行中のスレッド。

  そのため、クラスでのJavaの単一継承、多重継承とインタフェースです。インタフェースのみ抽象メソッドであり、具体的な方法は、唯一のインタフェースクラスの実装によって達成することができるので、ケースクラスは、複数のインタフェースを実装し、メソッドの実装クラスは常にコールの時点で(曖昧がない)を呼び出すであろう、それは多くの場合の開発に使用されていますRunnableを。

パブリッククラススレッド1を実装したRunnable { 
    @Override 
    公共ボイドラン(){ 
        System.out.printlnは( "III")。
    } 
    パブリック静的無効メイン(文字列[] args){ 
        スレッド1 RT =新しいスレッド1()。
        スレッドt =新しいスレッド(RT); 
        t.start(); 
    } 
}

3.スレッドプール

  創造と破壊の多くは、リソースを大量に消費する時間のスレッドは、我々はあなたが使用した後、直接使用を引き継ぐために使用する必要があるとき、彼らは中央で、スレッドプールを形成するために管理され、事前にいくつかのスレッドを作成することができ、置きますバックスレッドプールへ。

エグゼキュータのフレームワーク

  java.util.cocurrentパケットは、フレーム開始スレッドにより制御され、閉鎖を行う、並行プログラミング動作は次のように一般的な方法である5つのエグゼキュータクラス静的ファクトリメソッドによって作成された、簡略化することができます。

3.1スレッドプールを作成します

  1. newFixedThreadPool:固定サイズのスレッドプールを作成します。スレッドプールのサイズが到達すると、スレッドの実行異常終了すると、スレッドプールは、新しいスレッドを追加するための最大は、変更されません。

    エグゼキュークラス{パブリック
        / * 
        機能:タスクLinkedBlockingQueue無制限の長さを格納するキューをブロックし、固定長で作成スレッドプール。プール内のスレッドが生存期間を限定されるものではなく、すなわち、スレッドプールのスレッドは常に、スレッドプールのシャットダウンしない限り存在します。
        * / 
        パブリック静的ExecutorServiceのnewFixedThreadPool(nthreadsの値INT){ 
           スレッド/ *パラメータ番号コアサイズ(スレッドの最小数)、スレッドの数<パラメータは、スレッドが実行可能実行作成されたときに
            第二のスレッド*パラメータの最大数を、ときにスレッドの数> =パラメーターIIは、(パラメータ5)ワークキューに実行可能であろう
            、アイドル状態のスレッドを維持するための最大時間を生存時間を維持するために、* 3つのパラメータを。
            *パラメータの4倍単位
            *保存のタスクパラメータ5つのブロッキングキュー
            *公共ThreadPoolExecutor(corePoolSize int型、
                                  int型maximumPoolSize、
                                  ロングkeepAliveTimeが、
                                  TimeUnitでユニット、 
                                  BlockingQueueの<Runnableを> workQueu 
            * / 
                ThreadPoolExecutor新しい新しい返す(nThreads1、nThreads2、
                                              0L、TimeUnit.MILLISECONDSを、
                                              新しい新しいLinkedBlockingQueue <Runnableを>()); 
        } 
        // ... 
    } 
    ExecutorServiceのES = Executors.newFixedThreadPool(20である); 
    //スレッドがあればプール内のスレッドの数が多すぎるか小さすぎる、パフォーマンスに影響します
  2. newCachedThreadPool:アイドルスレッドの60秒スレッドプールのキャッシュを作成します。スレッドプールのスレッドのサイズが必要な処理タスクを超えた場合、それは部分的に自由に回復するタスクの数、このスレッドプールとインテリジェントには、タスクを処理する新しいスレッドを追加するときに、スレッド(60秒は、タスクを実行しません)。

    エグゼキュータクラスは{パブリック     
        パブリック静的ExecutorServiceのnewCachedThreadPoolは(){ 
                新しいて、新しいThreadPoolExecutor(0は、Integer.MAX_VALUE、戻り
                                              60L、TimeUnit.SECONDS、
                                              新しい新しいSynchronousQueue <Runnableをを>()); 
         } 
        // ...    
    } 
    ExecutorServiceのES = Executors.newCachedThreadPool (); 
    //欠点が突然交通多くの時間があり、それは多数のスレッドを作成します。
  3. シングルスレッドのスレッドプールを作成します。これは、すべてのタスクのシングルスレッドのシリアル実行と等価であるだけで、スレッドプールのスレッドの仕事、です。唯一の理由は、異常終了のこのスレッド場合は、それに代わる新しいスレッドがあるでしょう。

    ExecutorServiceのES = Executors.newSingleThreadExecutor()。
    //等同于ExecutorServiceのES = Executors.newFixedThreadPool(1)。
  4. newScheduledThreadPool:スレッドプールのサイズ制限を作成します。タイミングと定期的にタスクを実行する必要性をサポートするために、このスレッドプール。

    静的な無効メインパブリック(文字列[]引数){ 
            ScheduledExecutorService Executors.newScheduledThreadPool SES =(1); 
            ses.scheduleWithFixedDelay(Runnableを新しい新しい(){ 
                @Override 
                公共ボイドRUN(){ 
                    試み{ 
                        のThread.sleep(3000); 
                    }キャッチ( E InterruptedExceptionある){ 
                        e.printStackTrace(); 
                    } 
                    のSystem.out.println(新しい新しい日付()); 
                } 
            }、最初のサイクル時間* / 1000 / *スタート、各サイクルの2000 / *時間間隔* / 、TimeUnit.MILLISECONDS); 
        }
  5. newSingleThreadScheduledExecutor:シングルスレッドのスレッドプールを作成します。タイミングと定期的にタスクを実行する必要性をサポートするために、このスレッドプール。

3.2スレッドプール内のスレッドを使用して

  スレッドプールのExecutorServiceのを介して取得するためのエグゼキュータクラスは、このインタフェースを達成しました。あなたは、実行()またはスレッドプールに適切なタスクに提出する()メソッドを提出呼び出すことができます。

 1. (Runnableを)を実行:このメソッドは、Runnableを例を受け取り、非同期実行。

パブリック静的無効メイン(文字列[] args){ 
        ExecutorServiceのES = Executors.newCachedThreadPool()。
//今後の未来= 
        es.execute(新しいRunnableを(){ 
            @Override 
            ます。public void実行(){ 
                {試す
                    のThread.sleep(1000); 
                }キャッチ(InterruptedExceptionある電子){ 
                    e.printStackTrace(); 
                } 
                System.out.printlnは( "スレッドを実行してください。"); 
            } 
        })。
        System.out.println( "オーバー"); 
 } 
/ *出力:
 *以上
 *のスレッドを実行します。
 * /

2. (Runnableを)提出: submit(Runnable)execute(Runnable)の違いは、前者が返すことができるということである未来のオブジェクトを、今後は、私たちが提出したタスクが終了したかどうかを確認することができ、オブジェクトが返されました。

静的な無効メインパブリック(文字列[]引数)がスローExecutionException、InterruptedExceptionある{ 
        ExecutorServiceのExecutors.newCachedThreadPool ES =(); 
        未来の未来= es.submit(Runnableを新しい新しい(){ 
            @Override 
            公共ボイドRUN(){ 
                試み{ 
                    のThread.sleep( 1000); 
                }キャッチ(InterruptedExceptionあるE){ 
                    e.printStackTrace(); 
                } 
                のSystem.out.println( "スレッドRUN。"); 
            } 
        }); 
        Future.get(); //future.get()メソッド意志すなわち、第二待って、上記スレッドが完了するまでブロックを生成
        (「上」)のSystem.out.printlnを; 
} 
/ *出力: 
 RUNスレッドが*。
 *以上
 * /

3. (呼び出し可能)を提出してください submit(Callable)submit(Runnable)のような、また呼び出しパラメータコーラブルクラスのメソッドがRunable値を返す、とすることはできません、Futureオブジェクトを返します。

公共の静的な無効メイン(文字列[]引数)がExecutionException、InterruptedExceptionある{スロー
        ExecutorServiceのES = Executors.newCachedThreadPool()。
        今後の未来= es.submit(新しい呼び出し可能(){ 
            @Override 
            パブリックオブジェクトの呼び出し()例外{スロー
                {試す
                    のThread.sleep(1000); 
                }キャッチ(InterruptedExceptionある電子){ 
                    e.printStackTrace(); 
                } 
                リターン「は、スレッドを実行します。 "; 
            } 
        })。
        ストリングRS =(文字列)future.get(); //future.get()方法会产生阻塞
        のSystem.out.println( "オーバーと" + RS)。
 }
/ *出力:
 *以上のスレッドを実行します。
 * /

InvokeAny 4(コレクション<呼び出し可能延び?<T> タスク>>):スレッドが完了すると、パラメータ・タイプのセットを受け取るメソッド呼び出し可能な入力、タスク複数のスレッドが、対応する独立したスレッドの実行を開始する、それが返さ他のスレッドが終了している間。

公共の静的な無効メイン(文字列[]引数)スローExecutionException、InterruptedExceptionある{ 
        ExecutorServiceのES = Executors.newFixedThreadPool(3); 
        セット<呼び出し可能<文字列>>呼び出し可能=新しいHashSetの<呼び出し可能<文字列>>(); 
        呼び出し可能。 ({新しい呼び出し可能の<string>()を追加
            @Override 
            例外{スローパブリック文字列コール()
                ;のThread.sleep(2000)に
                戻り、 "最初のタスク"; 
            } 
        }); 
        callables.add(新しい呼び出し可能の<string>(){ 
            @Override 
            パブリック文字列コール()例外{スロー
                のThread.sleep(1000)。 
                リターンを」2番目のタスク ";
            } 
        }); 
        callables.add(新しい呼び出し可能の<string>(){ 
            @Override 
            パブリック文字列()の呼び出しは例外{スロー
                ;のThread.sleep(3000)に
                戻り、 "第三のタスク"; 
            } 
        }); 
        文字列のRS = ESの。 invokeAny(呼び出し可能)。
        System.out.println(RS)。
} 
/ *出力
 *第2のタスク
 * /

invokeAll 5に(コレクション<Callableを拡張する?<T> タスク>>)パラレルコーラブルコレクション型で実行されるすべてのメソッド。

公共の静的な無効メイン(文字列[]引数)スローExecutionException、InterruptedExceptionある{ 
        ExecutorServiceのES = Executors.newFixedThreadPool(3); 
        セット<呼び出し可能<文字列>>呼び出し可能=新しいHashSetの<呼び出し可能<文字列>>(); 
        呼び出し可能。 ({新しい呼び出し可能の<string>()を追加
            @Override 
            例外{スローパブリック文字列コール()
                ;のThread.sleep(2000)に
                戻り、 "最初のタスク"; 
            } 
        }); 
        callables.add(新しい呼び出し可能の<string>(){ 
            @Override 
            パブリック文字列コール()例外{スロー
                のThread.sleep(1000)。 
                リターンを」2番目のタスク ";
            } 
        }); 
        callables.add(新しい呼び出し可能の<string>(){ 
            @Override 
            パブリック文字列コール()例外{スロー
                のThread.sleep(3000); 
                リターン"タスク3"; 
            } 
        }); 
        リスト<今後の<string >>リスト= es.invokeAll(呼び出し可能)。
        以下のための(将来の<string>未来:リスト){ 
            文字列S = future.get()。
            System.out.println(S); 
        } 
}

6. shotdown():このメソッドを呼び出した後、スレッドプールが閉鎖され、この方法は、呼び出しはすぐに戻ります一度実行が終了した後、スレッドプールのすべてが、非同期方式である、閉じ続ける提出されました。

7.shotdownNow():呼び出しはすぐに戻りたら、このメソッドを呼び出した後、スレッドプールが閉鎖され、方法が提出されましたが、非同期メソッドでスレッドプールの即時かつ完全な閉鎖を、キャンセルされます。

8. awaitTermination(タイムアウト、単位):そのスレッドプールのスレッドの実行が完了するように、この方法は、ブロックを現在のスレッドと呼ばれ、タイムアウトの最大待ち時間は、この方法は、shotdown / shotdownNowを呼び出した後に有効必要とします。

パブリッククラススレッドセーフな実装のRunnable { 
    プライベート静的int型カウント= 0; 
    @Override 
    公共ボイドRUN(){ 
        ため(INT I = 0; I ++は、私は10 <){ 
            COUNT ++; 
        } 
    } 
    パブリック静的な無効メイン(文字列[]引数)がスロー{InterruptedExceptionある
        ExecutorServiceのES = Executors.newFixedThreadPool(10); 
        {(; I 20は、<I ++はI = 0 INT)ため
            es.execute(THREADSAFEを新しい新しい()); 
        } 
        es.shutdown(); //スレッドを追加することは許されません、閉じる非同期接続プール
        es.awaitTermination(10L、TimeUnit.SECONDS); //タスクスレッド接続プールの完了を待つ
        のSystem.out.println(COUNT); 
    } 
} 
/ *出力 
* 200であります
* /

リファレンス

  1. パン永華Javaのマルチスレッドおよびソケット..戦闘マイクロサービスフレームワーク[M]電子工業プレス.2019.3

  2. スレッドプールエグゼキュークラスを作成するための分析のいくつかの方法

 

 

おすすめ

転載: www.cnblogs.com/helloworldcode/p/11715306.html