售票员手里面 有两张5元的,张(20)、孙(10)、赵(5)、王(10)、刘(5)按这个顺序买票,括号里面是钱数,输出结果应该为:
张给售票员20元钱
售票员请张靠边等一会
孙给售票员10元钱,售票员卖给孙一张票,找赎5元
张结束等待,继续买票
张给售票员20元钱,售票员卖给张一张票,找赎15元
赵给售票员五元钱,售票员卖给赵一张票,不必找零
王给售票员10元钱,售票员卖给王一张票,找赎5元
刘给售票员五元钱,售票员卖给刘一张票,不必找零
但是 执行多次,有很多结果,求解释
源程序:
public class ex_04 {
public static void main(String args[]){
String s1="张",s2="孙",s3="赵",s4="王",s5="刘";
Cinema canema=new Cinema(s1,s2,s3,s4,s5);
Thread zhang,sun,zhao,wang,liu;
zhang=new Thread(canema);
sun=new Thread(canema);
zhao=new Thread(canema);
wang=new Thread(canema);
liu=new Thread(canema);
zhang.setName(s1);
sun.setName(s2);
zhao.setName(s3);
wang.setName(s4);
liu.setName(s5);
zhang.start();
sun.start();
zhao.start();
wang.start();
liu.start();

}
}class Cinema implements Runnable{
TicketSeller seller;
String name1,name2,name3,name4,name5;
Cinema(String s1,String s2,String s3,String s4,String s5)
{
seller=new TicketSeller();
name1=s1;
name2=s2;
name3=s3;
name4=s4;
name5=s5;

}
public void run()
{
if(Thread.currentThread().getName().equals(name1))
{
seller.sellTicket(20);
}
else if(Thread.currentThread().getName().equals(name2))
{
seller.sellTicket(10);
}
else if(Thread.currentThread().getName().equals(name3))
{
seller.sellTicket(5);
}
else if(Thread.currentThread().getName().equals(name4))
{
seller.sellTicket(10);
}
else if(Thread.currentThread().getName().equals(name5))
{
seller.sellTicket(5);
}
}

}
class TicketSeller{
int fiveNumber=2,tenNumber=0,twentyNumber=0;
public synchronized void sellTicket(int receiveMoney)
{
String s=Thread.currentThread().getName();
if(receiveMoney==5){
fiveNumber=fiveNumber+1;
System.out.println(s+"给售票员五元钱,售票员卖给"+s+"一张票,不必找零");
}
else if(receiveMoney==10){
while(fiveNumber<1){
try{
System.out.println(s+"给售票员10元钱");
System.out.println("售票员请"+s+"靠边等一会");
wait();
System.out.println(s+"结束等待,继续买票");
}
catch(InterruptedException e){}
}
fiveNumber=fiveNumber-1;
tenNumber=tenNumber+1;
System.out.println(s+"给售票员10元钱,售票员卖给"+s+"一张票,找赎5元");
}
else if(receiveMoney==20){
while(fiveNumber<1||tenNumber<1){
try{
System.out.println(s+"给售票员20元钱");
System.out.println("售票员请"+s+"靠边等一会");
wait();
System.out.println(s+"结束等待,继续买票");
}
catch(InterruptedException e){}
}
fiveNumber=fiveNumber-1;
tenNumber=tenNumber-1;
twentyNumber=twentyNumber+1;
System.out.println(s+"给售票员20元钱,售票员卖给"+s+"一张票,找赎15元");
}
notifyAll();
}
}

解决方案 »

  1.   

    你无法控制线程进入活动状态的顺序,即使你是按照一定顺序调用了start()
      

  2.   

    如果你想控制线程的执行顺序,可以试试在run函数的最后加上代码让线程休眠一会:
    public void run()
        {
            if(Thread.currentThread().getName().equals(name1))
            {
            seller.sellTicket(20);
            }
            else if(Thread.currentThread().getName().equals(name2))
            {
            seller.sellTicket(10);
            }
            else if(Thread.currentThread().getName().equals(name3))
            {
            seller.sellTicket(5);
            }
            else if(Thread.currentThread().getName().equals(name4))
            {
            seller.sellTicket(10);
            }
            else if(Thread.currentThread().getName().equals(name5))
            {
            seller.sellTicket(5);
            }
         
            try {
    Thread.currentThread().sleep(100);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }    
    }
      

  3.   


    这样只是在每个线程开始后让他们都睡一会儿,还是不能控制他们进入sellTicket的顺序。你要想控制顺序,得在start()之后让主线程睡一会儿,再启动下一个线程。另外楼主,如果你想要控制顺序,何必用线程?并行执行才是用线程的目的,不如把题目改成5个人争着去售票口买票吧还有一个练习题,让5个人排队买票。这是一个producer / consumer的模式,可以去看看Java的BlockingQueue
      

  4.   


    public class Andy {

    public static void main(String[] args) {
    People p1 = new People("张先生", 0, 20);
    People p2 = new People("孙先生", 1, 10);
    People p3 = new People("赵先生", 2, 5);
    People p4 = new People("王先生", 3, 10);
    People p5 = new People("刘先生", 4, 5);
    Seller s = new Seller();
    new MyThread(p5, s).start();
    new MyThread(p4, s).start();
    new MyThread(p3, s).start();
    new MyThread(p2, s).start();
    new MyThread(p1, s).start();
    }
    }class Seller {
    private int left_money = 10;
    private int[] queue = {0, -1, -1, -1, -1}; //排队序列,0表示可以买票,-1表示尚未买票,1表示已经买票,2表示零钱不够无法买票
    Lock lock = new ReentrantLock();
    Condition cond = lock.newCondition();

    /**
     * 此函数负责卖票,
     * 首先检测当前这个人是不是排在队伍最前头,
     * 再检测手里的零钱是否够找零
     * 每次卖掉一张票,或者因为没零钱让一个人靠边站之后,
     * 要设置下一个可以买票的人
     */
    public void sellTicit(People p) {
    lock.lock();
    int money = p.getMoney();
    int n = p.getIndex();
    try {
    while (!isTurned(n) || money > left_money+5) {
    if(money > left_money+5) {
    System.out.println(p.getName()+"给售票员"+money+"元钱");
    System.out.println("零钱不够,售票员让他靠边等一会");
    queue[n] = 2; //将此人标记为零钱不够无法买票
    int i;
    for(i=n+1; i<5; i++) { //在他后面找一个尚未买票的
    if(queue[i] != 1)
    break;
    }
    queue[i] = 0; //将其设置为0,表示下次该他买票
    cond.signalAll();
    }
    cond.await();
    }
    System.out.println(p.getName()+"给售票员"+money+"元钱, 售票员卖给他1张票,找零"+(money-5)+"元");
    left_money += 5; //卖出一张票后,售票员手中的钱增加5元
    queue[n] = 1; //当前这个人设置为已经买票
    int i;
    for(i=0; i<n; i++) { //找找在此人之前,是否有因无法找零而买不到票的
    if(queue[i] == 2)
    break; 
    }
    if(i==n) //如果之前所有人都已买到票,则看看他后面有谁尚未买票
    for(i=n+1; i<5; i++) {
    if(queue[i] == -1)
    break;
    }
    if(i<5)
    queue[i] = 0; //设置下一个买票的人
    cond.signalAll();
    }catch (InterruptedException e) {

    }finally {
    lock.unlock();
    }
    }

    private boolean isTurned(int n) { //检测是否轮到此人买票
    int i=0;
    for(i=0; i<5; i++) {
    if(queue[i]==0)
    break;
    }
    if(n==i)
    return true;
    else
    return false;
    }
    }class People {
    private String name;
    private int index;
    private int money;



    public People(String name, int index, int money) {
    this.name = name; //姓名
    this.index = index; //排在队伍的第几名
    this.money = money; //手里有多少钱
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public int getIndex() {
    return index;
    }
    public void setIndex(int index) {
    this.index = index;
    }
    public int getMoney() {
    return money;
    }
    public void setMoney(int money) {
    this.money = money;
    }
    }
    class MyThread extends Thread {
    People p;
    Seller s; public MyThread(People p, Seller s) {
    super();
    this.p = p;
    this.s = s;
    } @Override
    public void run() {
    s.sellTicit(p);
    }
    }