マルチスレッドプログラム設計の23のポイント


1.マルチスレッドにはメインメモリとワークメモリがあり、JVMにはメインメモリがあり、すべてのスレッドがデータを共有することを担当している.各スレッドには、JVMのstack領域とheap領域にメインメモリとワークメモリのデシベルが独自のワークメモリを持っています.
2.スレッドの状態は、「Ready」、「Running」、「Sleeping」、「Blocked」、および「Waiting」のいくつかの状態であり、「Ready」は、スレッドがCPU割り当ての実行を許可する時間を待っていることを示す.
3.スレッドの実行順序は私たちが作成した順序ではなく、CPUがスレッドを処理する順序は不確定であり、決定が必要な場合は手動で介入し、setPriority()メソッドを使用して優先度を設定する必要があります.
4.1つのスレッドがいつ実行されるか、2つ以上のスレッドが同じリソースにアクセスするときにsynchronizedが必要であることを知ることはできません.
5.各スレッドは自己登録され、実際にはどこかに参照が存在するため、ゴミ回収メカニズムは「手の施しようがない」.
6.Daemonスレッド一般的なスレッドの違いは、メインプログラムが終了するとDaemonスレッドが終了する点です.
7.1つのオブジェクトのsynchronizedメソッドはすべて1つのロックを共有し、このロックは複数のメソッドが共通メモリに対して同時に行う書き込み操作を防止することができる.synchronized staticメソッドは、クラス範囲内で互いにロックされ得る.
8.重要な共有リソースにアクセスするすべての方法は、synchronizedに設定する必要があります.そうしないと、正常に動作しません.
9.既知の方法が競合を起こさないと仮定し、synchronizedを使用しないでパフォーマンスを向上させるのが最も賢明です.
10.「同期」メソッドが変数を変更し、私たちのメソッドがこの変数(読み取り専用かもしれない)を使用する場合は、自分のメソッドもsynchronizedに設定したほうがいいです.
11.synchronizedは継承できません.親のメソッドがsynchronizedである場合、子のリロードメソッドでは同期は継承されません.
12.スレッドがBlockedを塞ぐ原因はいくつかあります.
(1)スレッドはいくつかのIO操作を待っている
(2)スレッドは別のオブジェクトの「同期」メソッドを呼び出そうとするが,そのオブジェクトはロック状態であり,一時的に使用できない.
13.原子型操作(atomic)、原始型変数(primitive)に対する操作は原子型のatomicである.これらの操作はスレッドが安全であることを意味しますが、ほとんどの場合、私たちは正しく使用できません.i=i+1、iはint型で、元の変数に属しています.
(1)メインメモリからi値をローカルメモリに読み出す.
(2)ローカルメモリからスレッドワークコピーに値をロードする.
(3)変数1をロードする.
(4)iを1とする.
(5)変数iに結果を与える.
(6)スレッドのローカルワークコピーにiを保存する.
(7)メインメモリに書き込む.
なお、原子型動作は、第1ステップから第2ステップの読み出しおよび第6ステップから第7ステップの書き込みに限られ、iの値は、i=i+1を同時に実行するマルチスレッド割り込みによって邪魔される可能性がある(第4ステップ).
doubleおよびlong変数は非原子型(non−atomic)である.配列はobject非原子型である.
14.13条の理由により、我々の解決策は以下の通りである.
 
class xxx extends Thread{
   //i 
  private int i;

  public synchronized int read(){ return i;}

  public synchronized void update(){ i = i + 1;}

  ..........

  }

15.Volatile変数、volatile変数は、主メモリと一致しなければならないことを保証し、実際には「変数の同期」であり、すなわち、longまたはdouble変数の前に使用されるようなvolatile変数の動作は原子型であることを示す.
16.yield()を使用するとCPUが自動的に放棄され、sleepよりもパフォーマンスが向上する場合があります.
17.sleep()とwait()の違いは、wait()メソッドが呼び出されるとロックが解除されますが、同期メソッドまたはコードブロック内でのみ使用できます.
18.製造により同期範囲を縮小し、可能な限りコードブロック同期を実現し、wait(ミリ秒数)は指定されたミリ秒数でwaitを終了することができる.wait()にはnotisfy()またはnotifyAll()に蹴られる必要があります.
19.2つのスレッド間のリアルタイム通信を構築する方法は、いくつかのステップに分けられます.
(1). PipedWriterとPipedReaderとそれらの間のパイプを作成します.
PipedReader in = new PipedReader(new PipedWriter())
(2). 情報を送信するスレッドが開始される前に、外部のPipedWriterを内部のWriterインスタンスoutに導く
(3). 情報を受け取るスレッドが始まる前に、外部のPipedReaderをその内部のReaderインスタンスinに導く
(4). これによりoutに入れたすべての物度がinから抽出される.
20.synchronizedがもたらす問題は性能の低下に加えて、最大の欠点はデッドロックDeadLockをもたらすことであり、慎重に設計することでデッドロックを防止するしかない.他に方法がないのも、スレッドが馴染まない原因の一つである.stop()suspend()resume()メソッドとdestory()メソッドを使用しないでください.
21.大量のスレッドが詰まっている場合、最も優先度の高いスレッドが先に実行されます.ただし、低レベルスレッドが実行されないことを示さず、実行確率が小さいだけです.
22.スレッドグループの主な利点は、単一のコマンドを使用してスレッドグループ全体の操作を完了することです.スレッドグループを使用する必要はめったにありません.
23.マルチスレッドのパフォーマンスを向上させるには、次のいくつかの方法があります.
すべての可能なBlockの場所を検査して、できるだけ多くsleepあるいはyield()とwait()を使います;
できるだけsleep(ミリ秒数)の時間を延長します.
実行するスレッドは100個を超えなくても、あまり多くはできません.
異なるプラットフォームlinuxまたはwindows、および異なるJVMの実行性能には大きな違いがあります.