Итак, мой проект представляет собой симулятор карточного типа. У меня есть класс дилера, игрока и кучи. Куча — это общий ресурс, куда дилер кладет одну (не несколько, а только одну) карту, а игрок забирает ее. Я создаю два потока, один для дилера и один для игрока. Дилер должен дождаться, пока его уведомят о том, что игрок взял карту; затем он продолжит класть новую карту вниз. Точно так же игрок будет ждать, пока его не уведомят о том, что дилер положил карту вниз, а затем игрок заберет карту.
Также предполагается наличие механизма, который и игрок, и крупье будут использовать для подтверждения того, что им разрешено класть или брать карту из кучи. Я использовал логическое значение; если логическое значение истинно или ложно, игроку или дилеру может быть разрешено или не разрешено выполнять соответствующие действия.
В то же время игрок и крупье засыпают на случайный интервал времени, после чего они просыпаются и проверяют, могут ли они выполнять свои действия. Если они не могут, они будут ждать, пока они не будут уведомлены.
Мой вопрос касается методов ожидания и уведомления. В чем разница между ожиданием и сном? Как сделать так, чтобы игрок/дилер просыпался ото сна и был вынужден ждать, пока его уведомят, если ему не разрешено брать/добавлять карту из кучи? Кроме того, правильно ли я делаю синхронизацию?
Извините, что мой код действительно грязный. Пожалуйста, обращайтесь за разъяснениями.
import java.util.ArrayList;
public class Heap {
static String topCard;
static boolean newCardChecker = false;
public Heap(){
}
public synchronized static void putOnHeap(String Card){
topCard = Card;
newCardChecker = true;
}
public synchronized static String takeFromHeap(){
newCardChecker = false;
return topCard;
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
public class Dealer implements Runnable {
String[] deck = {"2 Hearts", "3 Hearts", "4 Hearts", "5 Clubs", "6 Clubs", "7 Clubs",
"8 Hearts", "9 Hearts", "10 Hearts" , "10 Spades"};
ArrayList<String> myHand = new ArrayList<>();
Heap theHeap;
public Dealer(Heap heap){
theHeap = heap;
for(int i = 0; i < deck.length; i++){ //adds deck to dealer's hand
myHand.add(deck[i]);
}
}
public void run(){
//synchronized(theHeap){
while(myHand.size() != 0){ //repeat until dealer's hand is empty
if(Heap.newCardChecker != false){
try{
Thread.currentThread().wait();
}catch(InterruptedException e){
}
theHeap.putOnHeap(myHand.get(0));
System.out.println("Placed card " + myHand.get(0) + " onto heap");
myHand.remove(0); //although dealer's cards in hand is being removed, the dealer had
//the same cards as deck so I print out the deck contents at the end
Thread.currentThread().notify();
}
try{
Thread.currentThread().sleep(3000 + (int)Math.random() * 10000);
}catch(InterruptedException e){
}
}
//}
System.out.println("Hello, I am a dealer. Here is my hand: " + Arrays.deepToString(deck));
}
//While not last card, put a card on heap. sleep for a rand time
//print "put card x on heap"
public static void main(String[] args){
Heap heap = new Heap();
Thread t1 = new Thread(new Dealer(heap));
Thread t2 = new Thread(new Player(heap));
//Thread t3 = new Thread(new Heap());
t1.start();
t2.start();
}
}
import java.util.ArrayList;
public class Player implements Runnable {
ArrayList<String> myHand = new ArrayList<String>();
Heap theHeap;
public Player(Heap heap){
theHeap = heap;
}
public void run(){
//synchronized(theHeap){
while(myHand.size() != 10){
try{
Thread.currentThread().sleep(3000 + (int)Math.random() * 10000);
}catch(InterruptedException e){
}
if(Heap.newCardChecker != true){
try{
Thread.currentThread().wait();
}catch(InterruptedException e){
//System.err.println("Exception caught");
}
myHand.add(theHeap.takeFromHeap());
System.out.println("Took card " + myHand.get(myHand.size() - 1) + " from heap");
Thread.currentThread().notify();
}
}
System.out.println("Hello, I am a player. Here is my hand: " + myHand.toString());
}
//}
//While less than or equal to 10 card, take card from heap. Then sleep.
//"print took card x from heap"
}
wait()
иnotify()
. Но это сложно и очень легко ошибиться. Я бы, например, всю синхронизацию и ожидание/уведомление поместил в классHeap
, потому что на данный момент нет ничего, что гарантировало бы, чтоHeap.newCardChecker
будет проверяться перед тем, как положить или взять карту, и даже там, где она проверяется, нет никакой гарантии, что вы увидите самое актуальное значение. - person biziclop   schedule 20.01.2015