スレッド間の通信と同期
1. スレッドAが完了した後にスレッドBを実行する
/**
* Aが完了した後にBを実行
*/
@Test
public void bWaitA() {
Thread A = new Thread(() -> {
System.out.println("A: 作業開始!!");
System.out.println("A: 作業終了!!");
});
Thread B = new Thread(() -> {
System.out.println("B: Aの完了を待つ");
try {
A.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("B: 作業開始!!");
System.out.println("B: 作業終了!!");
});
B.start();
A.start();
}
2. Aが一部を実行し、Bが完了した後にAが残りを実行する
/**
* Aが一部を実行し、Bが完了した後にAが残りを実行
* A 1, B 1, B 2, B 3, A 2, A 3
*/
@Test
public void aWaitB() {
Object lock = new Object();
Thread A = new Thread(() -> {
System.out.println("A: ロック待ち");
synchronized (lock) {
System.out.println("A: ロック取得");
System.out.println("A 1");
try {
System.out.println("A: waitでロック解放、再取得待ち");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A: 唤醒后,重新获取锁控制权");
System.out.println("A 2");
System.out.println("A 3");
}
});
Thread B = new Thread(() -> {
System.out.println("B: ロック制御権取得待ち");
synchronized (lock) {
System.out.println("B: ロック制御権取得");
System.out.println("B 1");
System.out.println("B 2");
System.out.println("B 3");
System.out.println("B: 完了、notify呼び出し");
lock.notify();
}
});
A.start();
B.start();
}
3. A, B, Cが完了した後にDを実行する
/**
* A, B, Cが完了した後にDを実行
*/
@Test
public void dWaitABC() {
int worker = 3;
CountDownLatch countDownLatch = new CountDownLatch(worker);
new Thread(() -> {
System.out.println("D: 他のスレッドの完了待ち");
try {
countDownLatch.await();
System.out.println("すべてのスレッドが完了、D開始");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
for (char threadName = 'A'; threadName <= 'C'; threadName++) {
final String threadNameStr = String.valueOf(threadName);
new Thread(() -> {
System.out.println(threadNameStr + ": 作業中");
System.out.println(threadNameStr + ": 作業完了");
countDownLatch.countDown();
}).start();
}
}
4. 三人の選手が準備完了後同時に走り出す
/**
* 三人の選手が準備完了後同時に走り出す
*/
@Test
public void runABCWhenAllReady() {
int runner = 3;
CyclicBarrier cyclicBarrier = new CyclicBarrier(runner);
final Random random = new Random();
for (char runnerName = 'A'; runnerName <= 'C'; runnerName++) {
final String runnerNameStr = String.valueOf(runnerName);
new Thread(() -> {
long prepareTime = random.nextInt(1000) + 100;
System.out.println(runnerNameStr + ": 準備中");
try {
Thread.sleep(prepareTime);
} catch (Exception e) {
e.printStackTrace();
}
try {
System.out.println(runnerNameStr + ": 準備完了、他のスレッド待ち");
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("すべてのスレッドが準備完了、" + runnerNameStr + " 開始");
}).start();
}
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
5. スレッド間のデータ共有
/**
* スレッド間のデータ共有
*/
@Test
public void shareData() {
ShareData shareData = new ShareData();
for (int i = 1; i <= 2; i++) {
new Thread(new MyIncreRunnable(shareData)).start();
new Thread(new MyDecreRunanble(shareData)).start();
}
}
class MyIncreRunnable implements Runnable {
private ShareData shareData;
public MyIncreRunnable(ShareData shareData) {
this.shareData = shareData;
}
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
shareData.increment();
}
}
}
class MyDecreRunanble implements Runnable {
private ShareData shareData;
public MyDecreRunanble(ShareData shareData) {
this.shareData = shareData;
}
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
shareData.decrement();
}
}
}
class ShareData {
private int count = 0;
public synchronized void increment() {
count++;
System.out.println(Thread.currentThread().getName() + " inc " + count);
}
public synchronized void decrement() {
count--;
System.out.println(Thread.currentThread().getName() + " dec " + count);
}
}