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

时间:2015-01-19 23:36:10

标签: java multithreading synchronization wait notify

所以我的项目是卡片类型模拟。我有经销商,玩家和Heap类。堆是一个共享资源,经销商放置一张(不是多张,只有一张)牌,玩家将把它拿起来。我创建了两个线程,一个用于经销商,一个用于玩家。经销商应该等到他被告知玩家已拿起卡片;然后他将继续放下一张新牌。同样,玩家将等到他被告知经销商已经放下一张牌,然后玩家将选择该牌。

还应该有一种机制,玩家和经销商都会使用这种机制来确认他们是否可以从堆中放入或取出一张卡。我用了一个布尔值;如果布尔值为true或false,则允许或不允许玩家或经销商执行相应的操作。

与此同时,玩家和经销商将被设置为随机时间间隔进入休眠状态,然后他们将被唤醒并检查他们是否可以执行其操作。如果他们不能,他们会等到通知他们。

我的问题涉及wait和notify方法。等待和睡眠有什么区别?如何让玩家/经销商从睡眠中醒来,他们被迫等到他们被通知,如果他们不被允许从堆中取出/添加卡?另外,我是否正确地进行了同步?

很抱歉我的代码非常混乱。请询问澄清。

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"

}

1 个答案:

答案 0 :(得分:1)

解决问题的一种方法是使Heap成为一个固定容量为一个元素的ArrayBlockingQueue。 Dealer只会将put()卡片循环到堆上,而Player会从堆中循环,take()卡片。

只要堆中已有卡,经销商就会在put()调用中自动阻塞(即等待),并且只要堆为空,Player就会在take()调用中阻塞。

您可以将sleep()次调用放入任一循环来模拟经销商和玩家花费时间。


关于sleep()wait()之间的区别;

通过在永远不会收到通知的对象sleept(t)上调用foo.wait(t),您可以获得与foo完全相同的效果。所以,技术上sleep()是多余的:没有它我们都可以相处。

但名字很重要。当我在程序中看到foo.wait()时,我希望调用者正在等待其他某个线程执行与foo对象相关的操作,当我看到sleep()时,我知道调用者只是浪费了一些时间。