Java仮想マシン同時プログラミング-2.同時ポリシー

1788 ワード

2.1分けて治める
 
スレッド数の決定:少なくともプロセッサコア数ほどのスレッドを作成したいと考えています.これにより、可能な限り多くのプロセッサコアが問題解決に投入されることが保証されます.次のコードを使用すると、システムで使用可能なプロセッサのコア数を簡単に取得できます.
Runtime.getRuntime().availableProcessors();

したがって、アプリケーションの最小スレッド数はプロセッサのコア数に等しいはずです.すべてのタスクが計算が密集している場合は、プロセッサが使用できるコア数を作成すると、マルチスレッドになります.タスクが50%を超える時間がブロックされている場合、これらのタスクはIO密集型であり、プロセッサのコア数の数の倍以上のスレッドを作成する必要があります.スレッド数計算式は、スレッド数=CPU使用可能コア数/(1−ブロック係数)を参照し、ブロック係数は0と1の間である.密集型タスクを計算するブロック係数は0であり,IO密集型タスクのブロック係数は1に近い.完全なブロックの任務は中止に決まっているので、ブロック係数が1に達する心配はありません.必要なスレッド数をよりよく決定するには、次の2つの重要なパラメータを知る必要があります.
 
  • プロセッサ使用可能コア数
  • タスクのブロック係数
  • 1つ目のパラメータは簡単に決定でき、2つ目のパラメータはいくつかの性能分析ツールやjavaを採用することができる.lang.management APIは、システムI/O動作にかかるスレッドの時間とCPU集中タスクにかかる時間との比を決定する.
        
    タスクの数の決定:問題を解決する過程で、各サブタスクに負荷を割り当てるよりも、プロセッサを常にビジー状態に保つほうがお得です.問題を処理する観点から、まだ完了するタスクがある限り、空きプロセッサコアがないことを保証する必要があります.
         
    共有可変状態を回避し,分離可変性または共有不変性で置き換えなければならない.現代のスレッドAPIとスレッドプールを十分に利用します.
    Javaの古いスレッドAPIは今まだ武術の場所がありますか?
     
    古いスレッドAPIは機能的に多くの欠陥がある.たとえば、スレッドの再起動は許可されていないため、スレッドの実行が遅くなると、Threadクラスのインスタンスを破棄する必要があります.そこで、複数のタスクを同時に処理するためには、多重化前に作成されたものではなく、常に新しいスレッドを開く必要があります.
     
    wait()やnotify()のような関数はスレッド間同期が必要であり,スレッド間通信を行うタイミングがいつなのか判断するのは難しい.join()関数は、スレッドの消滅を処理する論理に集中し、終了するタスクの処理を無視します.
    また、synchronizedキーワードの粒度が太すぎます.このキーワードは、スレッドがロックを取得していない場合のタイムアウトロジックを提供しず、反発領域の同時読み取りも許可しない.synchronizedを使用すると、スレッドセキュリティに関するユニットテストページが難しくなります.
    現在、Doug Leaらが開発しているjava.util.concurrentパッケージの次世代同時APIは、古いスレッドAPIによく取って代わっています.
     
  • 以前コードでThreadクラスとそのメソッドが使用されていた点では,
  • の代わりにExecutorServiceクラスおよび関連クラスを用いることが考えられる.
  • ロックのプロセスをよりよく制御するには、ロックインタフェースとその方法を使用することが望ましい.
  • 以前のコードでwait/notifyメソッドが使用されていた場所では、
  • の代わりにCyclicBarrierやCountdownLatchのような同期ツールが使用できるようになりました.