###【概要】
2スレッドを生成し、そのスレッドどうしでじゃんけんをして結果を表示します。
GitHubにアップしてあります → threadJankenGame
###【コード】
JankenCallable.java
package game;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import game.Janken.Hand;
public class JankenCallable implements Callable<Janken.Hand> {
public static int playerNumber = 1;
public final static Object lock = new Object();
@Override
public Hand call() throws Exception {
TimeUnit.SECONDS.sleep(1);
synchronized (lock) {
playerNumber++;
if (playerNumber % 2 == 0) {
System.out.println("1人目の名前 : " + Thread.currentThread().getName());
} else {
System.out.println("2人目の名前 : " + Thread.currentThread().getName());
}
}
return Janken.getHand();
}
}
Janken.java
package game;
public class Janken {
public enum Hand {
GUU("グー"), CHOKI("チョキ"), PAA("パー");
private final String hand;
private Hand(String hand) {
this.hand = hand;
}
public String getHand() {
return hand;
}
}
/**
* じゃんけんの結果を表示する
*
* @param firstPlayerHand
* 1人目の出した手
* @param secondPlayerHand
* 2人目の出した手
*/
public static void getGameResult(Hand firstPlayerHand, Hand secondPlayerHand) {
// じゃんけんの勝者を1人目と仮置きする
Hand winner = firstPlayerHand;
if (firstPlayerHand == Hand.GUU && secondPlayerHand == Hand.PAA) {
winner = secondPlayerHand;
} else if (firstPlayerHand == Hand.CHOKI && secondPlayerHand == Hand.GUU) {
winner = secondPlayerHand;
} else if (firstPlayerHand == Hand.PAA && secondPlayerHand == Hand.CHOKI) {
winner = secondPlayerHand;
}
System.out.println(getPlayerHand(firstPlayerHand, secondPlayerHand));
if (firstPlayerHand == secondPlayerHand) {
System.out.println("あいこです。");
} else if (winner == firstPlayerHand) {
System.out.println("1人目の勝ちです。");
} else if (winner == secondPlayerHand) {
System.out.println("2人目の勝ちです。");
}
System.out.println("");
}
/**
* ランダムにじゃんけんの手を取得する
* @return じゃんけんの手
*/
public static Hand getHand() {
double random = Math.random() * 10;
if (6.6 < random) {
return Hand.GUU;
} else if (3.3 < random) {
return Hand.CHOKI;
}
return Hand.PAA;
}
/**
* プレイヤーが出した手を表示する
*
* @param firstPlayerHand
* 1人目の出した手
* @param secondPlayerHand
* 2人目の出した手
* @return 1人目と2人目の手の出し方
*/
private static String getPlayerHand(Hand firstPlayerHand, Hand secondPlayerHand) {
return "1人目の手は" + String.format("%s", firstPlayerHand.getHand()) + " : 2人目の手は"
+ String.format("%s", secondPlayerHand.getHand());
}
}
Main.java
package game;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import game.Janken.Hand;
public class Main {
// スレッドプール数 2人専用のじゃんけんゲームのため"2"限定となってしまう
private static final int THREAD_POOL_COUNT = 2;
// じゃんけんのゲーム回数
private static final int GAME_COUNT = 3;
public static void main(String[] args) {
ExecutorService executorService = Executors.newScheduledThreadPool(THREAD_POOL_COUNT);
List<Future<Hand>> jankenList = new ArrayList<>();
for (int i = 0; i < GAME_COUNT * 2; i++) {
Future<Hand> future = executorService.submit(new JankenCallable());
jankenList.add(future);
}
int count = 0;
Hand firstPlayerHand = null;
Hand currentPlayerHand = null;
for (Future<Hand> hand : jankenList) {
count++;
try {
currentPlayerHand = hand.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
// 1人目と2人目の手が決まったところで結果を表示する
if (count % THREAD_POOL_COUNT == 0) {
Janken.getGameResult(firstPlayerHand, currentPlayerHand);
} else {
firstPlayerHand = currentPlayerHand;
}
}
}
}
###【実行例】
1人目の名前 : pool-1-thread-1
2人目の名前 : pool-1-thread-2
1人目の手はグー : 2人目の手はグー
あいこです。
1人目の名前 : pool-1-thread-1
2人目の名前 : pool-1-thread-2
1人目の手はグー : 2人目の手はパー
2人目の勝ちです。
1人目の名前 : pool-1-thread-2
2人目の名前 : pool-1-thread-1
1人目の手はパー : 2人目の手はグー
1人目の勝ちです。
###【参考】
ExecutorServiceを使って、Javaでマルチスレッド処理
synchronizedブロックに使用されているStaticObjectが変更される場合、実質synchronizedされていない
###【問題点・改善点】
・3人(3スレッド)以上ではじゃんけんゲームができない。
・結果のコロン(:)の位置を揃えたかった。
###【おまけのコーナー】
スレッド処理は難しい。