如何运行两个线程周期性?
How to run two thread periodically?
我被要求制作一个 Player class(实现 运行nable ),我在其中实现一个 运行 方法,该方法生成一个随机数并等待方法 getchoice 和return 生成的数字并通知 运行 的 getchoice 方法。然后是一个 RockPaperScissors class(实现了 Runnable),其中包含方法 运行 包含两个线程,每个线程都包含一个玩家对象,这两个线程应该互相对战 1000 次,然后它们应该被中断,然后它将显示每个玩家获胜的次数。 .我的问题是,当我的代码开始 运行 时,一开始它是完美的,但在随机回合中,它开始只玩很多次玩家 1,然后再转到玩家 2,这违背了游戏的目的:这里是代码:
public class RockPaperScissors implements Runnable {
int result1 ;
int result2 ;
int result3 ;
private final Object lock = new Object();
public void run(){
synchronized(lock){
Player a = new Player() ;
Player b = new Player() ;
Thread a1 = new Thread(a) ;
Thread b1= new Thread (b) ;
a1.start();
b1.start();
int choice1 = -100 ;
int choice2 = -1066 ;
for (int i = 0 ; i < 1000 ; i++){
try {
choice1 = a.getChoice();
} catch (InterruptedException e1) {
}
try {
choice2 = b.getChoice();
} catch (InterruptedException e) {
}
if (choice1 == 1 && choice2==0)
result2++;
else if (choice2 == 1 && choice1==0)
result1++;
else if (choice1 == 1 && choice2==1)
result3++ ;
else if (choice1 == 1 && choice2==2)
result1++ ;
else if (choice1 == 2 && choice2==1)
result2++ ;
else if (choice1 == 0 && choice2==2)
result1++ ;
else if (choice1 == 2 && choice2==0)
result2++ ;
else if (choice1 == 2 && choice2==2)
result3++ ;
else if (choice1 == 0 && choice2==0)
result3++ ;
}
这是 class 玩家:
public class Player implements Runnable {
private final Object lockvalue = new Object();
private int a;
public void run() {
synchronized (lockvalue) {
for (int counter = 0; counter < 1000; counter++) {
java.util.Random b = new java.util.Random();
a = b.nextInt(3);
System.out.println(counter);
try {
lockvalue.wait();
} catch (InterruptedException e) {
System.out.println("Thread player was interrupted");
}
}
}
}
public int getChoice() throws InterruptedException {
synchronized (lockvalue) {
lockvalue.notify();
return a;
}
}
}
如果我的程序 运行 完美无缺,计数器显示应该总是有一个从 0 到 1000 的数字,一个接一个重复,但在这里它是这样开始的,但后来它变得混乱,永远不会到达1000,有时停在 700 有时停在 800。我只能使用 notify() 、 notifyAll() 、 wait() 、 start() 、 interrupt() 和 join() 。
非常感谢您的帮助。谢谢
我会考虑使用 semaphore or a CountDownLatch 实现您的逻辑以获得更好的同步
http://tutorials.jenkov.com/java-util-concurrent/semaphore.html
http://tutorials.jenkov.com/java-util-concurrent/countdownlatch.html
您的实现和方法表明您不了解并发、它的工作原理以及应在何时应用。
我建议您阅读 Bruce Eckel 的 "Thinking in Java" 中的相应章节(并发) - http://www.mindview.net/Books/TIJ/
为了使您的代码正常工作您必须在 Player.getChoise()
中的 return 之前再添加一个 wait-notify
这里是固定版本:
RockPaperScissors.java
package game;
public class RockPaperScissors
{
static int player1wins = 0;
static int player2wins = 0;
static int draw = 0;
public static void main(String[] args) throws InterruptedException
{
int cycles = 1000;
Player player1 = new Player("Player-1", cycles);
Player player2 = new Player("Player-2", cycles);
new Thread(player1).start();
new Thread(player2).start();
for (int i = 0; i < cycles; i++)
{
Choice choice1;
Choice choice2;
choice1 = player1.getChoice();
System.out.println("Value 1 is definitely generated");
choice2 = player2.getChoice();
System.out.println("Value 2 is definitely generated");
System.out.printf("\n%3d\nPlayer1 - %8s\nPlayer2 - %8s\n", i, choice1.name(), choice2.name());
if (choice1 == choice2)
{
draw++;
System.out.println("Draw!");
}
else if (choice1 == Choice.ROCK)
{
if (choice2 == Choice.PAPER)
{
player2wins++;
System.out.println("2 wins!");
}
else
{
player1wins++;
System.out.println("1 wins!");
}
}
else if (choice1 == Choice.PAPER)
{
if (choice2 == Choice.SCISSORS)
{
player2wins++;
System.out.println("2 wins!");
}
else
{
player1wins++;
System.out.println("1 wins!");
}
}
else if (choice1 == Choice.SCISSORS)
{
if (choice2 == Choice.ROCK)
{
player2wins++;
System.out.println("2 wins!");
}
else
{
player1wins++;
System.out.println("1 wins!");
}
}
}
System.out.printf("Player 1 wins - %3d times;\n" +
"Player 2 wins - %3d times;\n" +
"Draw result - %3d times\n\n", player1wins, player2wins, draw);
System.out.printf("Player-1 cycles left = %d\n" +
"Player-2 cycles left = %d\n", player1.getCounter(), player2.getCounter());
}
}
Player.java
package game;
import java.util.Random;
public class Player implements Runnable
{
private Random random = new Random();
private int value;
private int counter;
private String name;
public Player(String name, int cycles)
{
this.name = name;
this.counter = cycles;
}
public synchronized void run()
{
while (true)
{
try
{
wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
value = random.nextInt(3);
System.out.println(name + " ... Value was generated = " + value);
notify();
// Otherwise your thread will never stop!
counter--;
if (counter <= 0)
{
System.out.println(name + " ... Limit of operations is exceeded.");
break;
}
}
}
public synchronized Choice getChoice() throws InterruptedException
{
System.out.println(name + " ... now can generate value");
notify();
System.out.println(name + " ... wait until value is generated");
wait();
Choice choice = Choice.values()[value];
System.out.println(name + " ... returning generated value: " + value);
return choice;
}
public int getCounter()
{
return counter;
}
}
Choise.java
package game;
public enum Choice
{
ROCK,
PAPER,
SCISSORS;
}
我被要求制作一个 Player class(实现 运行nable ),我在其中实现一个 运行 方法,该方法生成一个随机数并等待方法 getchoice 和return 生成的数字并通知 运行 的 getchoice 方法。然后是一个 RockPaperScissors class(实现了 Runnable),其中包含方法 运行 包含两个线程,每个线程都包含一个玩家对象,这两个线程应该互相对战 1000 次,然后它们应该被中断,然后它将显示每个玩家获胜的次数。 .我的问题是,当我的代码开始 运行 时,一开始它是完美的,但在随机回合中,它开始只玩很多次玩家 1,然后再转到玩家 2,这违背了游戏的目的:这里是代码:
public class RockPaperScissors implements Runnable {
int result1 ;
int result2 ;
int result3 ;
private final Object lock = new Object();
public void run(){
synchronized(lock){
Player a = new Player() ;
Player b = new Player() ;
Thread a1 = new Thread(a) ;
Thread b1= new Thread (b) ;
a1.start();
b1.start();
int choice1 = -100 ;
int choice2 = -1066 ;
for (int i = 0 ; i < 1000 ; i++){
try {
choice1 = a.getChoice();
} catch (InterruptedException e1) {
}
try {
choice2 = b.getChoice();
} catch (InterruptedException e) {
}
if (choice1 == 1 && choice2==0)
result2++;
else if (choice2 == 1 && choice1==0)
result1++;
else if (choice1 == 1 && choice2==1)
result3++ ;
else if (choice1 == 1 && choice2==2)
result1++ ;
else if (choice1 == 2 && choice2==1)
result2++ ;
else if (choice1 == 0 && choice2==2)
result1++ ;
else if (choice1 == 2 && choice2==0)
result2++ ;
else if (choice1 == 2 && choice2==2)
result3++ ;
else if (choice1 == 0 && choice2==0)
result3++ ;
}
这是 class 玩家:
public class Player implements Runnable {
private final Object lockvalue = new Object();
private int a;
public void run() {
synchronized (lockvalue) {
for (int counter = 0; counter < 1000; counter++) {
java.util.Random b = new java.util.Random();
a = b.nextInt(3);
System.out.println(counter);
try {
lockvalue.wait();
} catch (InterruptedException e) {
System.out.println("Thread player was interrupted");
}
}
}
}
public int getChoice() throws InterruptedException {
synchronized (lockvalue) {
lockvalue.notify();
return a;
}
}
}
如果我的程序 运行 完美无缺,计数器显示应该总是有一个从 0 到 1000 的数字,一个接一个重复,但在这里它是这样开始的,但后来它变得混乱,永远不会到达1000,有时停在 700 有时停在 800。我只能使用 notify() 、 notifyAll() 、 wait() 、 start() 、 interrupt() 和 join() 。
非常感谢您的帮助。谢谢
我会考虑使用 semaphore or a CountDownLatch 实现您的逻辑以获得更好的同步
http://tutorials.jenkov.com/java-util-concurrent/semaphore.html
http://tutorials.jenkov.com/java-util-concurrent/countdownlatch.html
您的实现和方法表明您不了解并发、它的工作原理以及应在何时应用。
我建议您阅读 Bruce Eckel 的 "Thinking in Java" 中的相应章节(并发) - http://www.mindview.net/Books/TIJ/
为了使您的代码正常工作您必须在 Player.getChoise()
中的 return 之前再添加一个 wait-notify这里是固定版本:
RockPaperScissors.java
package game;
public class RockPaperScissors
{
static int player1wins = 0;
static int player2wins = 0;
static int draw = 0;
public static void main(String[] args) throws InterruptedException
{
int cycles = 1000;
Player player1 = new Player("Player-1", cycles);
Player player2 = new Player("Player-2", cycles);
new Thread(player1).start();
new Thread(player2).start();
for (int i = 0; i < cycles; i++)
{
Choice choice1;
Choice choice2;
choice1 = player1.getChoice();
System.out.println("Value 1 is definitely generated");
choice2 = player2.getChoice();
System.out.println("Value 2 is definitely generated");
System.out.printf("\n%3d\nPlayer1 - %8s\nPlayer2 - %8s\n", i, choice1.name(), choice2.name());
if (choice1 == choice2)
{
draw++;
System.out.println("Draw!");
}
else if (choice1 == Choice.ROCK)
{
if (choice2 == Choice.PAPER)
{
player2wins++;
System.out.println("2 wins!");
}
else
{
player1wins++;
System.out.println("1 wins!");
}
}
else if (choice1 == Choice.PAPER)
{
if (choice2 == Choice.SCISSORS)
{
player2wins++;
System.out.println("2 wins!");
}
else
{
player1wins++;
System.out.println("1 wins!");
}
}
else if (choice1 == Choice.SCISSORS)
{
if (choice2 == Choice.ROCK)
{
player2wins++;
System.out.println("2 wins!");
}
else
{
player1wins++;
System.out.println("1 wins!");
}
}
}
System.out.printf("Player 1 wins - %3d times;\n" +
"Player 2 wins - %3d times;\n" +
"Draw result - %3d times\n\n", player1wins, player2wins, draw);
System.out.printf("Player-1 cycles left = %d\n" +
"Player-2 cycles left = %d\n", player1.getCounter(), player2.getCounter());
}
}
Player.java
package game;
import java.util.Random;
public class Player implements Runnable
{
private Random random = new Random();
private int value;
private int counter;
private String name;
public Player(String name, int cycles)
{
this.name = name;
this.counter = cycles;
}
public synchronized void run()
{
while (true)
{
try
{
wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
value = random.nextInt(3);
System.out.println(name + " ... Value was generated = " + value);
notify();
// Otherwise your thread will never stop!
counter--;
if (counter <= 0)
{
System.out.println(name + " ... Limit of operations is exceeded.");
break;
}
}
}
public synchronized Choice getChoice() throws InterruptedException
{
System.out.println(name + " ... now can generate value");
notify();
System.out.println(name + " ... wait until value is generated");
wait();
Choice choice = Choice.values()[value];
System.out.println(name + " ... returning generated value: " + value);
return choice;
}
public int getCounter()
{
return counter;
}
}
Choise.java
package game;
public enum Choice
{
ROCK,
PAPER,
SCISSORS;
}