/*
* Created on 2004-11-22
*/
/**
* @author TinyPandaBear
*
* Suppose you have three people and need a fair way to pick one of the three to
* win some prize or do some task. A common method is for each of them to flip a
* coin. If one coin comes up differently than the other two, that person wins.
* We can make a game out of this by repeating the contest a number of times and
* seeing who wins the most times.
*/
import java.util.*;
import java.io.*;
class Person extends Thread {
private static Random rand = new Random();
private PipedWriter[] out;
private PipedReader[] in;
// give every thread a unique ID, for toString()
private static int counter = 0;
private int number = counter++;
private int NumOfGames;
private int mywin = 0;
public Person() {/*default constructor*/}
public Person(int nog) {
NumOfGames = nog;
// two for other players, one for main() thread
out = new PipedWriter[3];
for (int i = 0; i < 3; i++)
out[i] = new PipedWriter();
}
public void setPipedReaderArray(Person[] p) throws IOException {
in = new PipedReader[2];
in[0] = new PipedReader(p[(number + 1) % 3].getPipedWriter(0));
in[1] = new PipedReader(p[(number + 2) % 3].getPipedWriter(1));
}
public PipedWriter getPipedWriter(int index) {
return out[index];
}
public void run() {
for (int i = 0; i < NumOfGames; i++) {
try {
int coin = rand.nextInt(2);
out[0].write(coin);
out[1].write(coin);
int diff = 0;
for (int j = 0; j < 2; j++) {
int other = (int) in[j].read();
if (coin != other)
diff++;
}
if (diff == 2) {
mywin++;
System.out.println("round " + i + " finished, " + this
+ "won.");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
try {
// report the results to main()
out[2].write(mywin);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public String toString() {
return "Person " + number + " ";
}
}
public class OddPersonWins {
static PipedReader[] readchannel = new PipedReader[3];
static Person[] p = new Person[3];
public static void main(String[] args) throws IOException {
// if use args[0] here, OutOfBoundException should be handled.
int rounds = 100;//Integer.parseInt(args[0]);
for (int i = 0; i < 3; i++) {
p[i] = new Person(rounds);
readchannel[i] = new PipedReader(p[i].getPipedWriter(2));
}
// set PipedReader should be after array has been initialized.
for (int i = 0; i < 3; i++)
p[i].setPipedReaderArray(p);
// threads should start after initialization finished.
for (int i = 0; i < 3; i++)
p[i].start();
// wait until all threads finished running.
for (int i = 0; i < 3; i++)
try {
p[i].join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("Total Games: " + rounds);
for (int i = 0; i < 3; i++) {
int won = (int) readchannel[i].read();
System.out.println("Player " + i + " won: " + won);
rounds -= won;
}
System.out.println("Total ties: " + rounds);
}
}
问题描述见源代码。
每个线程有5个pipe,两个read,三个writer,reader和writer相对应,多出来的writer用于和main()互交,在游戏完成时把自己的状态发给主线程用于统计信息。
每个回合各线程用rand.nextInt(2)生成一个或0或1的随机数,然后发给另外两个线程,然后从pipe里读另外两个线程发过来的结果,一一和自己的结果比较,如果都不同,那么就是自己赢,在mywin上加一,反之则什么都不作。当所有的回合都结束时,把mywin发给主线程,主线程收到三个线程分别发过来的mywin后,和总回合数相减,得到平局的数目。