import java.util.*;enum Color{ 红桃,黑桃,方片,梅花 }
public class TestThread
{
public static void main(String[] args)
{
CardHeap cardheap = new CardHeap();
Player p1 = new Player(cardheap, 1,"A");
Player p2 = new Player(cardheap, 2,"B");
Player p3 = new Player(cardheap, 3,"C");
Player p4 = new Player(cardheap, 4,"D"); p1.start();
p2.start();
p3.start();
p4.start();

}
}class CardHeap
{
LinkedList<Card> cardlist = new LinkedList<Card>();
int turn = 0;
public CardHeap()
{
String[] arr = {"1","2","3","4","5","6","7","8","9","10","J","Q","K"};
for(Color c : Color.values()) //生成牌堆
{
for(int j = 0;j < 13; ++j)
{
//把牌添加到该列表的尾
cardlist.addLast(new Card(arr[j],c));
}
}
Collections.shuffle(cardlist);//乱序
}

public int getlistSize()
{
return cardlist.size();
}
public int getTurn()
{
return turn;
}
public void setTurn(int turn)
{
this.turn = turn;
}

public Card getAndRemoveCard()
{
return (Card)cardlist.poll();
}
}class Player extends Thread
{
int x = 0;
int id;
CardHeap heap;
String playerName; public Player(CardHeap heap,int id,String name)
{
this.heap = heap;
this.id = id;
this.playerName = name;
} public void run()
{
while(true)
{
getcard();
x++;
if(heap.getlistSize() == 0)
{
System.out.println(playerName +"线程进行了"+ x+ "次调用");
return;
}
}
}

public synchronized void getcard()
{
try
{
if(heap.getTurn() + 1 == id)
{
Card c = heap.getAndRemoveCard();
if(c != null)
{
System.out.println(playerName + "取到" + c.getColor() + " " + c.getNum());
heap.setTurn((heap.getTurn() + 1) % 4);
}
}
else
{
wait();
}
notifyAll();
}
catch(Exception e)
{
System.out.println(e);
}
}
}class Card
{
String num;
Color color; public Card(String num, Color color)
{
this.num = num;
this.color = color;
} public String getNum()
{
return num;
} public Color getColor()
{
return color;
}
}运行结果如下:
A取到方片1这样就卡住了。为什么

解决方案 »

  1.   

    这个肯定有问题,假如第一个线程开始执行run方法,此时turn=0,发了一张牌,此时的turn为2,调用notifyAll方法之后,当前线程唤醒,而并不是所有的线程都唤醒了,所以下一次执行之后,其他线程处于wiat状态,而此时只有线程1处于非wait状态,但是条件又不成立,所以这个线程也会挂死.
      

  2.   


      public synchronized void getcard()
        {
            try
            {
                if(heap.getTurn() + 1 == id)
                {
                    Card c = heap.getAndRemoveCard();
                    if(c != null)
                    {
                        System.out.println(playerName + "取到" + c.getColor() + " " + c.getNum());
                        heap.setTurn((heap.getTurn() + 1) % 4);
                    }
                }
                else
                {
                    wait();
                }
                notifyAll();
            }
            catch(Exception e)
            {
                System.out.println(e);
            }
        }你这个同步有什么用,又不是共享资源。
    把这个放到CardHeap里面,多个线程去访问这个方法。
      

  3.   

    enum Color{ 红桃,黑桃,方片,梅花 }
    public class TestThread
    {
        public static void main(String[] args)
        {
            CardHeap cardheap = new CardHeap();
            Player p1 = new Player(cardheap, 1,"A");
            Player p2 = new Player(cardheap, 2,"B");
            Player p3 = new Player(cardheap, 3,"C");
            Player p4 = new Player(cardheap, 4,"D");        p1.start();
            p2.start();
            p3.start();
            p4.start();
            
        }
    }
    class CardHeap
    {
        LinkedList<Card> cardlist = new LinkedList<Card>();
        int turn = 0;
        public CardHeap()
        {
            String[] arr = {"1","2","3","4","5","6","7","8","9","10","J","Q","K"};
            for(Color c : Color.values()) //生成牌堆
            {
                for(int j = 0;j < 13; ++j)
                {
                    //把牌添加到该列表的尾
                    cardlist.addLast(new Card(arr[j],c));
                }
            }
            Collections.shuffle(cardlist);//乱序
        }
        
        public int getlistSize()
        {
            return cardlist.size();
        }
        public int getTurn()
        {
            return turn;
        }
        public void setTurn(int turn)
        {
            this.turn = turn;
        }
        
        public Card getAndRemoveCard()
        {
            return (Card)cardlist.poll();
        }
    }class Player extends Thread
    {
        int x = 0;
        int id;
        CardHeap heap;
        String playerName;    public Player(CardHeap heap,int id,String name)
        {
            this.heap = heap;
            this.id = id;
            this.playerName = name;
        }    public void run()
        {
            while(true)
            {
             synchronized(heap){//锁住对象
             getcard();
                    x++;
                    if(heap.getlistSize() == 0)
                    {
                        System.out.println(playerName +"线程进行了"+ x+ "次调用");
                        return;
                    }
             }
                
            }
        }
        
        public  void getcard()
        {
            try
            {
                if(heap.getTurn() + 1 == id)
                {
                    Card c = heap.getAndRemoveCard();
                    if(c != null)
                    {
                        System.out.println(playerName + "取到" + c.getColor() + " " + c.getNum());
                        heap.setTurn((heap.getTurn() + 1) % 4);
                    }
                }
                else
                {
                    yield(); // 切换线程
                }
            }
            catch(Exception e)
            {
                System.out.println(e);
            }
        }
    }class Card
    {
        String num;
        Color color;    public Card(String num, Color color)
        {
            this.num = num;
            this.color = color;
        }    public String getNum()
        {
            return num;
        }    public Color getColor()
        {
            return color;
        }
    }
      

  4.   

    wait(),notifyAll()用于对象上,而不用于Thread本身。通常wait()用在同步块中,表示释放锁定的共享资源并暂停,等待其他线程使用或处理此资源后notifyAll(),此线程继续执行。LZ的程序中wait()改为yield()或sleep(10),去掉notifyAll()就正常运行了。