Java 使用wait()和Notify()在4个线程之间执行线程间通信时获取IllegalMonitorStateException
我只想在下一轮等于当前线程时运行线程,例如,如果nextTurn=3,则只有为播放器3创建的线程才应运行,其他线程应处于等待状态。和其他线程一样,下面的程序持续无限次地改变回合,所以我想要一个特定于回合的线程应该无限次地运行Java 使用wait()和Notify()在4个线程之间执行线程间通信时获取IllegalMonitorStateException,java,multithreading,Java,Multithreading,我只想在下一轮等于当前线程时运行线程,例如,如果nextTurn=3,则只有为播放器3创建的线程才应运行,其他线程应处于等待状态。和其他线程一样,下面的程序持续无限次地改变回合,所以我想要一个特定于回合的线程应该无限次地运行 import static java.util.Collections.shuffle; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.ut
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;
}
}
导入静态java.util.Collections.shuffle;
导入java.util.ArrayList;
导入java.util.HashMap;
导入java.util.List;
导入java.util.Map;
导入java.util.Scanner;
公共类DemoMain{
公共静态void main(字符串[]args)引发InterruptedException{
//TODO自动生成的方法存根
int sizeOfDeck=31;
System.out.println(“在卡片组中输入卡片”);
ArrayList cardNumber=新的ArrayList(sizeOfDeck);
//对于(int i=0;i要在对象上使用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
或者,使用一个简单的对象表示回合的锁定,使用一个字符串
表示当前玩家:
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();
}
}
}
}
是的,我现在做更改,我没有得到任何错误,但它只运行一次,我想无限次地运行它
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();
}
}
}
}