JavaはCondationを使って指定スレッドを起動します.
5001 ワード
Reentrant Lockを使って同期を実現します.
まず、スレッドの機能を実現する機能クラスを作成します.
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を介して指定スレッドを起動させることができ、これによりスレッドスケジュールがより柔軟になる.
await 1の方法を実行してawait 2の方法を実行してsignal 1の方法を実行します. //threadBはconditionで待つスレッドのみを起動してawait 1を通知しました. await 1ロックを解除しました.signal 2を実行します.await 2をお知らせしました. await 2ロックが解除されました
まず、スレッドの機能を実現する機能クラスを作成します.
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ロックが解除されました