2017-01-29 5 views
-1

Ich werde gebeten, eine Player-Klasse zu erstellen (die Runnable implementiert), in der ich eine Run-Methode implementiere, die eine Zufallszahl generiert und auf die Methode getchoice und eine getchoice-Methode wartet, die die generierte Zahl zurückgibt und die Ausführung meldet. dann eine RockPaperScissors-Klasse (die Runnable implementiert), die Methoden enthält, die zwei Threads enthalten, die jeweils ein Spielerobjekt enthalten, diese zwei Threads sollten 1000 Mal gegeneinander spielen, dann sollten sie unterbrochen werden und dann wird angezeigt, wie oft jeder Spieler gewonnen . . Mein Problem ist, wenn mein Code anfängt zu laufen, ist es am Anfang perfekt, aber bei einer zufälligen Runde fängt es an, einfach mehrmals Spieler 1 zu spielen, bevor er zu Spieler 2 geht, was den Zweck des Spiels zunichte macht: hier ist der Code:Wie zwei Threads regelmäßig ausgeführt werden?

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


    } 

und das ist Klasse-Spieler:

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; 

    } 

} 

}

, wenn mein Programm läuft perfekt die Zähleranzeige immer die Nummer sollte von 0 bis 1000 beginnend dupliziert nacheinander, aber Hier fängt es an, aber dann wird es durcheinander gebracht nd es erreicht nie 1000, es stoppt manchmal bei 700 manchmal bei 800. alles, was ich verwenden darf, ist notify(), notifyAll(), wait(), start(), interrupt() und join().

Ihre Hilfe würde sehr geschätzt werden.

Dank
+0

Die Runnable sollte nur Informationen darüber, wer das Spiel gewinnt, nicht, wie oft es gespielt wird. – duffymo

+0

meinst du das lauffähige von RockPaperScissors? – Domarius

+1

Ja. Wenn ich du wäre, würde ich Threads vergessen, bis ich die Logik des Spiels mit zwei Spielern perfekt funktioniert hatte. Sobald Sie das haben, machen Sie es Multithread. – duffymo

Antwort

1

Ihre Implementierung und Ansatz zeigen, dass Sie die Parallelität nicht verstehen, wie es funktioniert und wann sollte angewendet werden.

Ich empfehle Ihnen entsprechende Kapitel (Concurrency) in Bruce Eckel "Denken in Java" zu lesen - http://www.mindview.net/Books/TIJ/

Um Ihren Code Arbeit Sie machen eine weitere hinzuzufügen wait-notify vor der Rückkehr in Player.getChoise() Hier

ist feste Version:

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

Vielen Dank. genau das was ich gesucht habe. kann ich fragen, warum sollte ich die while (true) wait() Schleife beim Lauf? und warum muss ich in getchoice warten? – Domarius

+0

while-Schleife macht in diesem Fall den gleichen Job wie Ihre for-Schleife (wegen Zähler), aber aus meiner Sicht sieht es logischer aus. wait in getChoice ist notwendig für die Generierung des nächsten Zufallswerts, da wait() den Monitor freigibt, getChoice stoppt und run() ausführen lässt. Sie können es auskommentieren und sehen, was passieren wird, deshalb habe ich einfache Log-Nachrichten hinzugefügt. – sergpank

Verwandte Themen