マルチスレッドの一般的な方法とロックに対する制御(詳細は不明)


1.sleep()
現在のスレッド(すなわち、この方法を起動するスレッド)を一時停止させ、他のスレッドに実行を継続させる機会を与えたが、オブジェクトのロックを解除しなかった。つまり、Synchronized同期ブロックがあれば、他のスレッドは依然として異なるアクセスで共有データにアクセスします。注意この方法は異常を捕獲します。
例えば、二つのスレッドが同時に実行されます。一つのスレッドの優先度はMAX_PRIORITY、もう一つはMIN_です。PRIORITYは、Sleep()の方法がない場合、優先度の高いスレッドのみが実行された後、優先度の低いスレッドのみが実行されます。ただし、優先度が高いスレッドsleep(5000)の場合は、低優先度で実行する機会がある。
つまり、sleep()は、優先度の低いスレッドを実行する機会を与えてもよく、もちろん、同じ優先度の高いスレッドを実行する機会を与えても良い。
2.ジョン()
join()メソッドは、この方法を起動するスレッドをこれまでに実行した後、つまり、この方法を呼び出したスレッドが実行されるのを待ってから実行を続けます。注意この方法も異常を捕獲します。
3.yield()
これはsleep()と同様に、ユーザによりどれぐらいの時間停止するかを指定できないだけであり、yield()方法は、同じ優先順位のスレッドを実行する機会しか与えない。
4.wait()とnotify()、notifyAll()
この3つの方法は、複数のスレッドによる共有データへのアクセスを調整するために使用されるので、Synchronized文ブロック内でこの3つの方法を使用しなければならない。Synchronizedというキーワードは共有データを保護するために使用され、他のスレッドから共有データへのアクセスを阻止すると前に述べました。しかし、このようなプログラムの流れは非常に柔軟ではないです。現在のスレッドがまだSynchronizedデータブロックを終了していない時、他のスレッドも共有データにアクセスする機会がありますか?この時はこの3つの方法で柔軟に制御します。
wait()メソッドは、現在のスレッドを停止させ、対象ロックマークをリリースし、他のスレッドをSynchronizedデータブロックに入れ、現在のスレッドを対象待ち池に入れます。notify()メソッドを呼び出した後、対象の待ち池から任意のスレッドを移動し、ロックフラグ待ちプールに入れます。ロック待ち池のスレッドだけがロックフラグを取得できます。ロックフラグ待ち池にスレッドがないとnotify()が機能しません。
notifyAll()は対象待ちのプールからその対象を待つスレッドを移動してロック待ちのプールに入れます。
この三つの方法は全部java.lang.Ojbectの方法です。
2.run()とstart()
これらの2つの方法は、並列処理が必要なコードをrun()にセットすると、start()メソッド起動スレッドが自動的にrun()メソッドを呼び出すことになります。これはJavaのメモリメカニズムによって規定されています。また、run()方法はpublicアクセス権限でなければなりません。戻り値タイプはvoidです。
3.キーワードSynchronized
このキーワードは共有データを保護するために使われています。もちろん、どのデータが共有データかを識別することが前提です。各オブジェクトには、スレッドがオブジェクトにアクセスすると、Synch ronizedによって修正されたデータが「ロック」され、他のスレッドへのアクセスが停止されます。現在のスレッドはこの部分のデータにアクセスした後、ロックマークを解放し、他のスレッドはアクセスできます。

public ThreadTest implements Runnable{ 
  public synchronized void run(){ 
    for(int i=0;i<10;i++){ 
      System.out.println(" " + i); 
    } 
  } 
  public static void main(String[] args) { 
    Runnable r1 = new ThreadTest(); 
    Runnable r2 = new ThreadTest(); 
    Thread t1 = new Thread(r1); 
    Thread t2 = new Thread(r2); 
    t1.start(); 
    t2.start(); 
  } 
} 
 
  //         i          ,      Synchronized        。  t1,t2         (r1,r2)   。//            ,  r1 r2     i          。 
          :Synchronized         
  Runnable r = new ThreadTest(); 
  Thread t1 = new Thread(r); 
  Thread t2 = new Thread(r); 
  t1.start(); 
  t2.start(); 
wait()とnotify()、notifyAll()はObject類の方法で、sleep()とyield()はThread類の方法です。
(1).よく使われるwait方法は、wait()とwait(long timeout)があります。
このオブジェクトのnotify()メソッドまたはnotifyAll()メソッドを他のスレッドで呼び出す前に、現在のスレッドが待機しています。
void wait(long timeout)は、他のスレッドでこのオブジェクトのnotify()メソッドまたはnotifyAll()メソッドを呼び出したり、指定された時間量を超える前に現在のスレッドが待機しています。
wait()を使用すると、スレッドが占有する「ロックマーク」をリリースし、スレッドがあるオブジェクトの中の他のsynchronizedデータを他のスレッドで使用することができます。
wait()とnotify()は対象のロックマークを操作しますので、synchronized関数またはsynchronized blockで呼び出さなければなりません。non-synchronized関数やnon-synchronized blockで呼び出すとコンパイルできますが、運転中にIL Monitors Stationの異常が発生します。
(2)Thread.sleep(long milis)には、時間パラメータが必要です。
sleep(long)は現在のスレッドを停止状態にするので、sleep()を実行するスレッドは指定された時間内には必ず実行されない。
sleep(long)は、優先度が低いスレッドを実行する機会を与えてもよく、もちろん、同じ優先度と高い優先度のスレッドを実行する機会を与えてもよい。
sleep(long)はロックマークを解放しない。
(3).yield()はパラメータがありません。
sleep方法は現在の運転中のスレッドをしばらく眠らせて、実行不可状態にします。この時間の長さはプログラムで設定されています。yield方法は現在のスレッドをCPUの占有権を譲っていますが、譲渡する時間は設定できません。
yield()もロックマークを解放しません。
実際には、yield()方法は、現在同じ優先度のスレッドが同じ動作状態にあるかどうかを確認し、ある場合はこのスレッドにCPUの占有権を付与し、そうでなければ元のスレッドを実行し続ける。したがって、yield()方法は「譲歩」と呼ばれ、他のスレッドに同じ優先順位で運転機会を与えた。
sleep方法は、優先度の低いスレッドが実行機会を得ることを可能にしているが、yield()方法が実行されると、現在のスレッドはまだ実行可能な状態にあるので、優先度の低いスレッドを譲ってもCPU占有権を得ることはできない。一つのオペレーティングシステムでは、優先度の高いスレッドがsleep方式を起動しておらず、I/Oブロッキングを受けていない場合、優先度の低いスレッドは、全ての優先度の高いスレッドの運転が終了するのを待つしかない。
yield()は現在のスレッドを実行可能な状態に戻すだけなので、実行可能な状態に入ったらすぐに実行される可能性があります。したがって、yield()は同じ優先度のスレッドのみ実行する機会があります。
以上、マルチスレッドの使い方とロックのコントロール(詳しくは分かりません)は、小編集が皆さんに共有している内容です。参考にしていただければと思います。よろしくお願いします。