如何运行两个线程周期性?

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;
}