JavaはCondationを使って指定スレッドを起動します.

5001 ワード

Reentrant Lockを使って同期を実現します.
まず、スレッドの機能を実現する機能クラスを作成します.
public class MyService {
	private Lock lock = new ReentrantLock();
	public void methodA() {
		try {
			lock.lock();  //  ,     synchronized
			
			System.out.println(Thread.currentThread().getName()+"   methodA      ");
			
			Thread.sleep(2000);
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			System.out.println(Thread.currentThread().getName()+"   methodA      ");
			lock.unlock(); //   
		}
		
	}
	
	public void methodB() {
		try {
			lock.lock();
			System.out.println(Thread.currentThread().getName()+"   methodB      ");
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			System.out.println(Thread.currentThread().getName()+"   methodB      ");
			lock.unlock();
		}
		
	}
}
4つのスレッドを作成し、2つのスレッドを実行し、2つのスレッドを実行します.
public static void main(String[] args) {
		final MyService service = new MyService();
		new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				service.methodA();
			}

		}).start();
		new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				service.methodA();
			}

		}).start();
		
		new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				service.methodB();
			}

		}).start();
		new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				service.methodB();
			}

		}).start();

	}
実行結果:
Thread-0はmethodAに入ります. ロックを得てThread-0を残します. そしてロックThread-1をリリースしてmethodAに入る. そして、Thread-1をロックして、methodAから離れます. そしてロックThread-2をリリースしてmethodBに入る. ロックを得てThread-2を残します. そしてロックThread-3をリリースしてmethodBに入る. ロックを得てThread-3を残します. ロックを解除する
現在のところ、ロックとロックの間はロックされています.この点はキーワードのsynchronizedと同じです.
指定スレッドをCondationで起動します.
synchronizedキーワードとwait()とnotify()/notifyAllを組み合わせてお知らせモデルを待つことができますが、一つの問題に直面しています.wait()に呼び覚まされたスレッドはランダムで、notifyAll()が呼び覚まされたのはすべてで、指定されたラインを呼び覚ますことができません.
RentrantrantLockは、Condationを介して指定スレッドを起動させることができ、これによりスレッドスケジュールがより柔軟になる.
public class MyService {
	private Lock lock = new ReentrantLock();
	private Condition condition  = lock.newCondition();
	private Condition condition2 = lock.newCondition();
	public void await1() {
		try {
			lock.lock();
			System.out.println("   await1   ");
			condition.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
			System.out.println("await1     ");
		}
	}
	
	public void await2() {
		try {
			lock.lock();
			System.out.println("   await2   ");
			condition2.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
			System.out.println("await2    ");
		}
	}
	
	public void signal1() {
		try {
			lock.lock();
			System.out.println("  signal1  ");
			condition.signal();
			System.out.println("   await1 ");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
			
		}
	}
	
	public void signal2() {
		try {
			lock.lock();
			System.out.println("  signal2  ");
			condition2.signal();
			System.out.println("   await2 ");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
			
		}
	}
}
四スレッドクラス
public class ThreadA extends Thread{
	private MyService service;
	public ThreadA(MyService service) {
		this.service = service;
	}
	
	public void run() {
		service.await1();
	}
}
public class ThreadAA extends Thread{
	private MyService service;
	public ThreadAA(MyService service) {
		this.service = service;
	}
	
	public void run() {
		service.await2();
	}
}
ThreadBは、conditionによって待つスレッドを起動するために使用される.
public class ThreadB extends Thread{
	private MyService service;
	public ThreadB(MyService service) {
		this.service = service;
	}
	
	public void run() {
		service.signal1();
	}
}
threadBBは、conditions 2によって待つスレッドを起動するために使用される.
public class ThreadBB extends Thread {
	private MyService service;
	public ThreadBB(MyService service) {
		this.service = service;
	}
	
	public void run() {
		service.signal2();
	}
}
public static void main(String[] args) {
	MyService service = new MyService();
	ThreadA threadA = new ThreadA(service);
	ThreadAA threadAA = new ThreadAA(service);
	ThreadB threadB = new ThreadB(service);
	ThreadBB threadBB = new ThreadBB(service);
	
	try {
		threadA.start();
		threadAA.start();
		Thread.sleep(300);
		threadB.start();
		ThreadA.sleep(3000);
		threadBB.start();
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
}
実行結果:
await 1の方法を実行してawait 2の方法を実行してsignal 1の方法を実行します.   //threadBはconditionで待つスレッドのみを起動してawait 1を通知しました.  await 1ロックを解除しました.signal 2を実行します.await 2をお知らせしました.  await 2ロックが解除されました