简体   繁体   English

等待并通知同步中的方法?

[英]Wait and Notify Methods in Synchronization?

So my project is a card type simulation. 所以我的项目是卡片类型模拟。 I have a Dealer, Player, and Heap class. 我有一个Dealer,Player和Heap类。 The heap is a shared resource where the dealer places one(not multiple, just one) card and the player will pick it up. 堆是一种共享资源,发牌人将一张(不是多张,只有一张)放置在纸牌上,然后玩家将其拿起。 I create two threads, one for a Dealer and one for a Player. 我创建了两个线程,一个用于经销商,一个用于玩家。 The dealer is supposed to wait until he is notified that the player has picked up the card; 发牌人应该等到通知他玩家已经拿起卡为止。 then he will proceed to place a new card down. 然后他将继续放下新卡。 Similarly, the Player will wait until he is notified that the dealer has placed a card down, and then the Player will pick the card up. 同样,玩家将一直等到收到发牌人放下纸牌的通知后,再将纸牌拿起。

There is also supposed to be a mechanism that both the Player and the Dealer will use to confirm that they are allowed to put or take a card from the Heap. 还应该有一种机制,玩家和发牌者都将使用这种机制来确认允许他们从堆中放置或取出卡片。 I used a boolean; 我用了一个布尔值; if the boolean is true or false, the Player or the Dealer could or could not be allowed to do their corresponding actions. 如果布尔值为true或false,则将允许或不允许玩家或交易者执行其相应的操作。

In the mean time, the Player and the Dealer are set to sleep for a random time interval, when they will then wake up and check to see if they can run their actions. 同时,玩家和庄家被设置为随机睡眠一段时间,然后他们将醒来并检查他们是否可以执行其动作。 If they cannot, they would wait until they are notified. 如果不能,他们将等到收到通知。

My question involves the wait and notify methods. 我的问题涉及等待和通知方法。 What is the difference between wait and sleep? 等待和睡眠有什么区别? How would I make is to that the Player/Dealer would wake up from a sleep, and they are forced to wait until they are notified, if they are not allowed to take/add a card from the heap? 我该如何使玩家/经销商从睡眠中醒来,如果不允许他们从堆中取出/添加卡,他们将被迫等待直到被通知为止? Also, am I even doing the synchronization properly? 另外,我什至没有正确进行同步?

Sorry that my code is really messy. 对不起,我的代码真的很乱。 Please ask for clarifications. 请要求澄清。

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"

} }

One way to solve your problem would be to make the Heap be an ArrayBlockingQueue with a fixed-capacity of one element. 解决您的问题的一种方法是使Heap成为一个固定容量为一个元素的ArrayBlockingQueue。 The Dealer would simply loop put() ting cards onto the heap, and the Player would loop, take() ing cards from the heap. Dealer只会循环put()婷卡到堆,而Player将环, take() ING卡从堆中。

The Dealer would automatically block (ie, wait) in the put() call whenever the heap already had a card in it, and the Player would block in the take() call whenever the heap was empty. 每当堆中已经有一张牌时,发牌者就会自动阻止(即等待) put()调用,而只要堆为空,发牌者就会自动阻止take()调用。

You could put sleep() calls into either loop to simulate the Dealer and the Player taking time. 您可以将sleep()调用放入任一循环中,以模拟经销商和玩家花费的时间。


Regarding the difference between sleep() and wait() ; 关于sleep()wait()之间的区别;

You could achieve the exact same effect as sleept(t) by calling foo.wait(t) on an object foo that never gets notified. 通过对永不通知的对象foo调用foo.wait(t) ,可以实现与sleept(t)完全相同的效果。 So, technically , sleep() is redundant: We could all get along without it. 因此,从技术上讲sleep()是多余的:没有它,我们都可以相处。

But names are important. 但是名字很重要。 When I see foo.wait() in a program, I expect that the caller is waiting for some other thread to do something related to the foo object, and when I see sleep() I know that the caller is just killing some time. 当我在程序中看到foo.wait()时,我期望调用foo.wait()在等待其他线程执行与foo对象相关的操作,并且当我看到sleep()我知道调用foo.wait()在消磨时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM