我只想在下一回合等于当前线程时运行线程,例如如果 nextTurn = 3,则只有为玩家 3 创建的线程应该运行,其他线程应该等待状态。对于其他线程也是如此,下面的程序不断地无限次地改变转弯,所以我希望特定于转弯的线程应该运行无限时间。
import static java.util.Collections.shuffle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class DemoMain {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
int sizeOfDeck = 31;
System.out.println("Enter cards in the Deck");
ArrayList<Integer> cardNumber = new ArrayList<Integer>(sizeOfDeck);
// for (int i = 0; i <= sizeOfDeck; i++) {
// Scanner input = new Scanner(System.in);
// cardNumber.add(input.nextInt());
// }
for(int i=0 ; i<=31;i++)
{
cardNumber.add(i);
}
System.out.println("Cards: "+ cardNumber );
shuffle(cardNumber);
List<Integer> Piles1 = cardNumber.subList(0, 4);
List<Integer> Piles2 = cardNumber.subList(4, 8);
List<Integer> Piles3 = cardNumber.subList(8, 12);
List<Integer> Piles4 = cardNumber.subList(12, 16);
List<Integer> player1Card = cardNumber.subList(16, 20);
List<Integer> player2Card = cardNumber.subList(20, 24);
List<Integer> player3Card = cardNumber.subList(24, 28);
List<Integer> player4Card = cardNumber.subList(28, 32);
Map<Integer, Integer> player1Map = getPlayerCards(player1Card);
Map<Integer, Integer> player2Map = getPlayerCards(player2Card);
Map<Integer, Integer> player3Map = getPlayerCards(player3Card);
Map<Integer, Integer> player4Map = getPlayerCards(player4Card);
Player p1 = new Player(player1Map, Piles1, Piles2, "Player1");
Player p2 = new Player(player2Map, Piles2, Piles3, "Player2");
Player p3 = new Player(player3Map, Piles3, Piles4, "Player3");
Player p4 = new Player(player4Map, Piles4, Piles1, "Player4");
p1.start();
p2.start();
p3.start();
p4.start();
}
private static Map<Integer, Integer> getPlayerCards(List<Integer> playerCard) {
Map<Integer, Integer> cardsMap = null;
for (Integer card : playerCard) {
if (cardsMap == null) {
cardsMap = new HashMap<Integer, Integer>();
}
Integer count = cardsMap.get(card);
if (count == null) {
cardsMap.put(card, 1);
} else {
cardsMap.put(card, cardsMap.get(card) + 1);
}
}
return cardsMap;
}
}
Player.java
import java.util.List;
import java.util.Map;
public class Player extends Thread {
private Map<Integer, Integer> holdings;
private List<Integer> deckToUseToDraw;
private List<Integer> deckToUseForDiscard;
private Integer currentlyDrawnCard;
private String playerTrun;
private boolean hasWon = false;
//static String Nextturn = "Player1";
StringBuffer Nextturn = new StringBuffer("Player1");
public Player(Map<Integer, Integer>holdings, List<Integer> drawDeck, List<Integer> discardDeck, String playerTurn) {
this.holdings = holdings;
this.deckToUseToDraw = drawDeck;
this.deckToUseForDiscard = discardDeck;
this.playerTrun = playerTurn;
}
public void run() {
try {
playNew();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void playNew() throws InterruptedException {
synchronized (Nextturn) {
while(true) {
if (! playerTrun.equalsIgnoreCase(String.valueOf(Nextturn))) {
try {
System.out.println("waiting: "+ playerTrun);
Nextturn.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("Running: "+playerTrun);
nextTurn();
Nextturn.notifyAll();
}
}
}
}
public void nextTurn()
{
if(playerTrun.equalsIgnoreCase("Player1"))
Nextturn = new StringBuffer("Player2");
else if(playerTrun.equalsIgnoreCase("Player2"))
Nextturn = new StringBuffer("Player3");
else if(playerTrun.equalsIgnoreCase("Player3"))
Nextturn = new StringBuffer("Player4");
else if(playerTrun.equalsIgnoreCase("Player4"))
Nextturn = new StringBuffer("Player1");
}
}
最佳答案
要在对象上使用wait()/notify()
,线程必须拥有该对象上的监视器。
由于您创建了一个新的 StringBuffer
实例并将其分配给 Nextturn
,同时线程拥有监视器:
Nextturn = new StringBuffer("Player1");
我认为当前线程丢失了监视器,或者至少在新对象上没有监视器。因此,您无法再在 Nextturn
上调用 wait()/notify()
。
例如这里:
nextTurn(); // you assign the variable to a new object
Nextturn.notifyAll(); // but you notify on that new object
作为替代方案,使用一个简单的对象来表示回合的锁定,并使用一个 String
来表示当前玩家:
final Object lockOnTurn = new Object();
String currentPlayer = "...";
// ..
private void playNew() throws InterruptedException {
synchronized (lockOnTurn) {
while(true) {
if (! playerTrun.equalsIgnoreCase(String.valueOf(currentPlayer))) {
try {
System.out.println("waiting: "+ playerTrun);
lockOnTurn.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("Running: "+playerTrun);
currentPlayer = nextTurn();
lockOnTurn.notifyAll();
}
}
}
}
关于java - 使用 wait() 和 Notify() 在 4 个线程之间执行线程间通信时出现 IllegalMonitorStateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57979454/