import java.util.HashMap;
/*
 * 6、编写三各类Ticket、SealWindow、TicketSealCenter
 *  分别代表票信息、售票窗口、售票中心。
 *  售票中心分配一定数量的票,
 *  由若干个售票窗口进行出售,
 *  利用你所学的线程知识来模拟此售票过程。
 */
//编写Ticket票信息类
class Ticket implements Runnable{
private String name;
private double price;
private HashMap<String, Double> map;
//构造方法
public Ticket()
{
super();
}

public Ticket(String name, double price)
{
super();
this.name = name;
this.price = price;
}
//此构造方法才是真正用的  传一个map集合  将此集合里的元素读取出来
//赋值给name  price
public Ticket(HashMap<String, Double> map){
this.map = map;
} //get   set 方法
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public double getPrice()
{
return price;
}
public void setPrice(double price)
{
this.price = price;
}
public HashMap<String, Double> getMap()
{
return map;
} public void setMap(HashMap<String, Double> map)
{
this.map = map;
} //这是电影票信息类的重写run方法   是第二个线程组  用来获取所购买的电影票的
//名字和单价
@Override
public void run()
{
try
{
Thread.sleep(100);
} catch (InterruptedException e)   
{
e.printStackTrace();
}
synchronized (new Object())
{

setName(Thread.currentThread().getName());
setPrice(getMap().get(Thread.currentThread().getName()));
}

}

}
//编写SealWindow售票窗口类
class SealWindow extends Ticket implements Runnable{
//定义变量ticket   记录卖出的票数
private int ticket;
//它的构造方法是传一个TicketSealCenter类的对象  此对象中有票数变量
//将票数传递给本类中的ticket
public SealWindow(TicketSealCenter tsc)
{
ticket = tsc.getNumber();
}
//重写run方法
@Override
public  void run()
{
//创建一个map集合   用来存放电影票的名字和单价
HashMap<String, Double> map = new HashMap<String, Double>();
map.put("分手大师", 60.0);
map.put("无极", 30.0);
map.put("一生一世", 40.0);
map.put("港囧", 60.0);
//将集合传入Ticket类的对象中
Ticket q = new Ticket(map);
Thread a = new Thread(q, "分手大师");
Thread a2 = new Thread(q, "一生一世");
Thread a3 = new Thread(q, "港囧");
Thread a4 = new Thread(q, "无极");
//线程并行执行
a.start();
a2.start();
a3.start();
a4.start();
//卖票
while(true){
try
{
Thread.sleep(100);
} catch (InterruptedException e)   
{
e.printStackTrace();
}
synchronized (new Object())
{
//如果票数大于0   则进行购票操作  谁抢到谁近   上面有个锁对象
//只要进来一个线程  其他线程就不能再进
if(ticket >0){
//分别获得电影票的信息
String n = q.getName();
double p = q.getPrice();
System.out.println(Thread.currentThread().getName()+"卖了一张:"+n+"电影票," +
"票价为:"+p+"元,目前还剩:"+(--ticket)+"张票,速来抢购哦~~");
}

}
}
}

}
//编写TicketSealCenter售票中心类
class TicketSealCenter{
private int number;
// 构造方法
public TicketSealCenter(int number){
this.number = number;
}
public TicketSealCenter(){
super();
}
//get    set  方法
public int getNumber()
{
return number;
}
public void setNumber(int number)
{
this.number = number;
}

}
public class Test6
{
public static void main(String[] args)
{
//创建售票中心对象   并将票数为100传给此类中的成员变量
TicketSealCenter tsc = new TicketSealCenter(100);
SealWindow target = new SealWindow(tsc);
Thread t = new Thread(target,"窗口1");
Thread t2 = new Thread(target,"窗口2");
Thread t3 = new Thread(target,"窗口3");
t.start();
t2.start();
t3.start();
}
}

解决方案 »

  1.   

    这么多代码,连个说明都没有。
    显然,synchronized (new Object())  这种写法是有问题的。
      

  2.   

    好乱啊,
    null 是因为线程a.start();
    a2.start();
    a3.start();
    a4.start();
    在它们执行前,有可能有线程已经执行到String n = q.getName();
    double p = q.getPrice();
    System.out.println(Thread.currentThread().getName()+"卖了一张:"+n+"电影票," +
    "票价为:"+p+"元,目前还剩:"+(--ticket)+"张票,速来抢购哦~~");这个时候还没setName
      

  3.   

    万分感谢你们帮我看   我不明白怎么设置锁对象才能保证在卖票窗口卖票之前  setName
      

  4.   

    我觉得在类的设计上要再考虑一下
    Ticket类用来记录名称、价格
    SealWindow类主要功能是出票,票不够向票务中心申请,应当在出票的时候确定票的信息。
    TicketSealCenter主要功能是根据现有票数视情向售票窗口分配票,分配票的时候需要同步,因为同一张票只能分配给一个窗口
      

  5.   

    HashMap是线程不安全的,试一下Map m = Collections.synchronizedMap(new HashMap());