JAvaはいくつかのスレッドの非同期転送同期の方法をまとめた.

4240 ワード

1つのappを作る時、1つの非同期実行のapiを使って、私が望んでいるのは同期実行で、いくつかの資料を調べて、いくつかの情況のスレッドの同期に対してまとめます.
一、共有資源の同期
質問:1つのリソースが複数のスレッドにアクセスされるとエラーが発生し、1つのスレッドのみがアクセスできる場合.
1.syschronized実装
syschonizedキーワードを使用すると、ブロックまたはメソッドへのアクセスを制限できます.すなわち、1つのスレッドがブロックまたはメソッドのアクセス権を取得すると、他のスレッドはアクセスできません.
public class synchronize_test implements Runnable{
	int num1 = 10;
	int num2 = 10;
	int num3 = 10;
	
	public void synchonized_test() {
		synchronized(this) {
			while(num1 > 0) { //            
				System.out.println(Thread.currentThread().getName() + "  num1=" + num1--);
			}
		}
		synchronized(this) { //            ,            ,                    
			while(num2 > 0) {
				System.out.println(Thread.currentThread().getName() + "  num2=" + num2--);
			}
		}
		while(num3 > 0) { //             (    )
			System.out.println(Thread.currentThread().getName() + "  num3=" + num3--);
		}
		
		
	}
	@Override
	public void run() {
		synchonized_test();
		
	}




	public static void main(String[] args) {
		synchronize_test sys = new synchronize_test();
		Thread t1 = new Thread(sys);
		Thread t2 = new Thread(sys);
		t1.start();
		t2.start();


	}
}

sychronizedを使用してメソッド(static以外)を修飾する場合、作用オブジェクトはこのメソッドが属するオブジェクトであり、同期ブロックと同じです.synchronizedがstaticメソッドまたは変数を修飾する場合、
オブジェクトを使用すると、オブジェクトではなくstaticが存在するクラスになります.staticメソッドはオブジェクトではなく、クラスに属します.
2.ロック実装
syschronizedの役割はオブジェクトまたはクラスであり,これは明らかに柔軟ではないが,ロックはそれよりも柔軟であることがわかる.
public class Lock_Test implements Runnable{
	int num1 = 10;
	int num2 = 10;
	Lock lock1 = new ReentrantLock();
	Lock lock2 = new ReentrantLock();
	
	public void synchonized_test() {
		lock1.lock(); //  lock1
		try {
			while(num1 > 0) { //            
				System.out.println(Thread.currentThread().getName() + "  num1=" + num1--);
			}
		} finally {
			lock1.unlock();
		}
		
		lock2.lock();//  lock2
		try {
			while(num2 > 0) {
				System.out.println(Thread.currentThread().getName() + "  num2=" + num2--);
			}
		} finally {
			// finally       
			lock2.unlock(); //  
		}
		
	
		
	}
	
	@Override
	public void run() {
		synchonized_test();
		
	}


	public static void main(String[] args) {

		Lock_Test lt = new Lock_Test();
		Thread t1 = new Thread(lt);
		Thread t2 = new Thread(lt);
		t1.start();
		t2.start();

	}
}

ここではReentrantLock、その他にReadWriteLockを使用しています.
ReentranLockの利点(以下から抜粋:https://github.com/pzxwhc/MineKnowContainer/issues/16)
ロックは、ロックを取得するプロセスを中断することができる.
lockはロックを取得しようとしますが、ロックが他のスレッドによって保持されている場合はfalseを返し、現在のスレッドをスリープさせません.
lockは、ロックを取得しようとすると、この時間範囲内でロックが取得されていない場合、要求を終了する時間パラメータを入力する.
synchronizedは自動的にロックを解除し、lockは自動的にロックを解除しません.
二、非同期回転同期
質問:一部のAPIは非同期であり、同期させたいと考えています.例えば、A、Bの2つの方法は非同期で実行され、いくつかのニーズのため、A方法を実行してからB方法を実行させたい.
1.countDownLatch解決
CountDownLatchは、インスタンスCountDownLatchオブジェクトのときに1回使用するごとに数字が入るカウンタのような同期を実現することができる.countDown()メソッドはカウントを1減らし、数字を0に減らすと、.await()メソッド後のコードは実行でき、0にならないまで待機をブロックします.
import java.util.concurrent.CountDownLatch;

public class CountDownLatch_test implements Runnable{
	private Integer num = null;
	
	private static CountDownLatch latch;
	
	public void setNumber() {
		num = 1;
	}
	
	public int getNumber() {
		return this.num;
	}

	@Override
	public void run() {
		if(Thread.currentThread().getName().equals("Thread-0")) { //t2  
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			this.setNumber();
			latch.countDown(); //   1
		}
		else if(Thread.currentThread().getName().equals("Thread-1")){ //t1  
			try {
				latch.await(); //       0
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("num = " + this.getNumber());
		}
		
	}

	public static void main(String[] args) {
		CountDownLatch_test c = new CountDownLatch_test();
		latch = new CountDownLatch(1);
		Thread t1 = new Thread(c);
		Thread t2 = new Thread(c);
		 t1.start();
		 t2.start();

	}

}

コードに示すように、t 1スレッドはnumの値を取得し、t 2スレッドはnumに値を付与し、明らかにt 2はt 1の前に実行を終了する必要があるが、t 2の実行時間はt 1より長いので、CountDownを使用してt 1をブロックしてt 2の完了を待つ.
また、await(設定パラメータ)に、一定時間に到達してもカウントが0にならないように実行することもできます.
他の方法は勉強しなければなりません.