老师给我们出了一个程序设计课题:设计一个多线程程序如下:设计一个火车售票模拟程序。假如火车站要有100张火车票要卖出,现在有5个售票点同时售票,用5个线程模拟这5个售票点的售票情况1、要求打印出每个售票点所卖出的票号2、各售票点不能售出相同票号的火车票补充:5个售票窗口不能分摊100张火车票,就是每个窗口卖固定数量和编号的火车票。我同学编写的都是每个窗口都卖20张火车票,从一号窗口开始卖1到20张,依次类推。如何实现每个窗口卖的票数随即,而且买的票号也随机呢?我们老师说,只要创建5个进程,然后共享一个类对象,然后把100张火车票运用while循环表示出来,这又怎么实现随机卖票呢。我开始想的是把100张火车票放到一个数组中,然后让每个线程随机的不重复的在这个数组中取元素,这样就可以实现随机卖票了。不知道这样可不可以,具体的我还是不知道怎么写这个程序,无从下手,而且好多java函数都不知道。谁能帮我分析一下这个小程序到底怎么写。

解决方案 »

  1.   

    你看看这个银行业务调度系统,基本一样的:http://blog.csdn.net/zhangxiaoxiang/archive/2011/04/01/6294132.aspx
      

  2.   

    我自己顶一下,我自己找到了段实现代码,但是不明白,
    class ThreadDemo1{
    public static void main (String[] args) {
         TestThread tt=new TestThread();
         new Thread(tt).start();
         new Thread(tt).start();
         new Thread(tt).start();
         new Thread(tt).start();
         new Thread(tt).start();
        }
    }class TestThread implements Runnable
    {
    int tickets=100;
    public void run()
    {
    while(true)
    {
    if(tickets>0)
    System.out.println (Thread.currentThread().getName()+"is selling:"+tickets--);
    }
    }
    }
    我不明白的是这五个进程为什么是随机访问TestThread类对象的。
      

  3.   

    用一个随机函数取票,票号不能重复,用boolean标记,初始化是false代表没卖,如果卖出去了标记true,你五个窗口要卖不同票,就把数组再分下,每个窗口对应一组票
      

  4.   

    其实用while没什么用了 我对次理解不不是很深刻了在此引用MLDN李兴华老师的一段代码希望对你有用:
    class MyThread implements Runnable{
    private int ticket = 100 ; // 假设一共有100张票
    public void run(){
    for(int i=0;i<100;i++){
    this.sale() ; // 调用同步方法
    }
    }
    public synchronized void sale(){ // 声明同步方法
    if(ticket>0){ // 还有票
    try{
    Thread.sleep(300) ; // 加入延迟
    }catch(InterruptedException e){
    e.printStackTrace() ;
    }
    System.out.println(Thread.currentThread().getName() + "卖票:ticket = " + ticket-- );
    } }
    };
    public class SyncDemo03{
    public static void main(String args[]){
    MyThread mt = new MyThread() ; // 定义线程对象
    Thread t1 = new Thread(mt) ; // 定义Thread对象
    Thread t2 = new Thread(mt) ; // 定义Thread对象
    Thread t3 = new Thread(mt) ; // 定义Thread对象
    Thread t4 = new Thread(mt) ; // 定义Thread对象
    Thread t5 = new Thread(mt) ;
    t1.start() ;
    t2.start() ;
    t3.start() ;
    t4.start() ;
    t5.start() ;
    }
    };
    如有什么不明白的可以在提了····
      

  5.   

    晕死了 刚刚给一个同样问题的 家伙看好程序 居然又看到一个差不多的 火车票问题....现在的年轻人都困在火车票上了?参考:
    import java.util.*;public class thread_test {
    private int n; // 存储起始售票的总数,并在该0~n内产生随机数模拟售票
    private int a;
    Object obj = new Object();
    LinkedList<Integer> number1 = new LinkedList<Integer>();// 为每个售票点存储售出的票
    LinkedList<Integer> number2 = new LinkedList<Integer>();
    LinkedList<Integer> number3 = new LinkedList<Integer>();
    LinkedList<Integer> number4 = new LinkedList<Integer>();
    LinkedList<Integer> number5 = new LinkedList<Integer>();
    LinkedList<Integer> h = new LinkedList<Integer>();// 存储总的票 thread_test(int n) {
    this.n = n;
    for (int i = 1; i <= this.n; i++) {
    this.h.add(i); // 初始化总共有多少张票
    }
    } void sale() {
    synchronized (obj) {
    String name = Thread.currentThread().getName();
    Random ra = new Random();
    do {
    //%100+1,取1~100随机数增加原先程序效率
    this.a = ra.nextInt()%this.n+1; // 随机产生一个数,模拟售票
    if (h.size() == 0){
    return;
    }
    } while (!this.h.contains(this.a)); // 检查该票是否售出,如果售出,则重新产生数字
    ckeck(name).add(this.a);// 将 将要售出的票添加到是那个售票窗口售出的那个链表中
    //必须强转类型,不明白看remove api说明
    this.h.remove((Integer) this.a);// 删除该数
    }
    } LinkedList<Integer> ckeck(String name) { // 检查是那个售票窗口即将售票,并放回该售票窗口的存储链表
    if ("线程T1".equals(name))
    return number1;
    else if ("线程T2".equals(name))
    return number2;
    else if ("线程T3".equals(name))
    return number3;
    else if ("线程T4".equals(name))
    return number4;
    else
    return number5; } void CreateThreadAndStart() {
    Runnable r = new Runnable() {
    public void run() {
    int i = 1;
    while (i <= n) { // 循环一百次,卖出一百张票
    sale();//
    i++;
    }
    System.out.println(number1 + " " + number1.size());
    System.out.println(number2 + " " + number2.size());
    System.out.println(number3 + " " + number3.size());
    System.out.println(number4 + " " + number4.size());
    System.out.println(number5 + " " + number5.size());
    System.out.println("-------------------");
    }
    };
    Thread t1 = new Thread(r, "线程T1");
    Thread t2 = new Thread(r, "线程T2");
    Thread t3 = new Thread(r, "线程T3");
    Thread t4 = new Thread(r, "线程T4");
    Thread t5 = new Thread(r, "线程T5");
    t1.start();
    t2.start();
    t3.start();
    t4.start();
    t5.start();
    } public static void main(String[] args) {
    new thread_test(100).CreateThreadAndStart();
    }
    }
      

  6.   

    这里定义了100张票,那启动的五个进程为什么要随机去访问这100张火车票,即使为什么要随机的去买票。我每次运行程序时五个进程打印出来的票号都不一样。
    难道这些都是cpu自己去随机计算的么?
      

  7.   

    刚写的代码,给你参考一下:package com.vbt;import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;public class TrainSaler { private Thread[] threads = null ;
    private int ticketCount = 100; //车票数
    private int currentNum = 1; //当前票号 //新建线程
    public void newThreads(int count)
    {
    threads = new Thread[count];
    for(int i=0;i<count;i++)
    {
    threads[i] = new Thread(new SalerThread(i+1));
    }
    }

    //启动线程
    public void startThreads()
    {
    if(null==threads)
    {
    System.out.println("没有初始化线程,有木有!!!");
    return;
    }
    for(int i=0;i<threads.length;i++)
    {
    threads[i].start();
    }
    }

    public static void main(String[] args)
    {
    TrainSaler trainTicketSaler = new TrainSaler();
    trainTicketSaler.newThreads(5);
    trainTicketSaler.startThreads();
    }

    //售票线程
    private class SalerThread implements Runnable
    {
    private int id; //线程ID
    //private Lock saleLock = new ReentrantLock();
    public SalerThread(int id)
    {
    this.id = id;
    }

    public synchronized void run()
    {
    //saleLock.lock();
    while(currentNum<=ticketCount)
    {
    System.out.println("窗口"+id+"售票,票号:"+currentNum++);
    }
    //saleLock.unlock();
    }

    }
    }
      

  8.   

    可以用while 啊
    代码如下:
    public class Example8_16 {
    public static void main(String[] args) {
    String s1 = "火车售票点A", s2 = "火车售票点B", s3 = "火车售票点C", s4 = "火车售票点D", s5 = "火车售票点E";
    Station station = new Station(s1, s2, s3, s4, s5);
    Thread threadA, threadB, threadC, threadD, threadE;
    threadA = new Thread(station);// 创建5个线程
    threadA.setName(s1);
    threadB = new Thread(station);
    threadB.setName(s2);
    threadC = new Thread(station);
    threadC.setName(s3);
    threadD = new Thread(station);
    threadD.setName(s4);
    threadE = new Thread(station);
    threadE.setName(s5);
    threadA.start();// 开启这5个线程
    threadB.start();
    threadC.start();
    threadD.start();
    threadE.start();
    }}class Station implements Runnable {
    int number = 100;
    String s1, s2, s3, s4, s5; Station(String s1, String s2, String s3, String s4, String s5) {
    this.s1 = s1;
    this.s2 = s2;
    this.s3 = s3;
    this.s4 = s4;
    this.s5 = s5;
    } @Override
    public void run() {
    // for (int i = 0; i < 100; i++) {
    // sellTicket();
    // }
    sellTicket();
    } public synchronized void sellTicket() {
    // if (number > 0) {
    // number--;
    // System.out.println(Thread.currentThread().getName() + "卖出一张票,票号为:"
    // + (100 - number));
    // }
    while (number > 0) {
    number--;
    System.out.println(Thread.currentThread().getName() + "卖出一张票,票号为:"
    + (100 - number));
    }
    }}
      

  9.   

    用BlockQueue不就完了,在BlockQueue放100个元素,每个线程一次从里面取一个元素
      

  10.   

    我写完了import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.LinkedBlockingQueue;public class BlockingQueueTest {
        public static void main(String[] args) {
            BlockingQueue<Integer> tickets = new LinkedBlockingQueue<Integer>();
            for (int i = 1; i <= 100; i++) {
                tickets.add(i);
            }
            new Window("window1",tickets).start();
            new Window("window2",tickets).start();
            new Window("window3",tickets).start();
            new Window("window4",tickets).start();
            new Window("window5",tickets).start();   
        }
    }class Window extends Thread {
        public String name;
        private BlockingQueue<Integer> tickets;    public Window(String name, BlockingQueue<Integer> tickets) {
            this.name = name;
            this.tickets = tickets;
        }
        public void run() {
            while(!tickets.isEmpty()){
                try {
                    int ticket = tickets.take();
                    System.out.println(name+" take ticket: "+ticket);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(name+" no more tickets ! ");
        }
    }
      

  11.   

    import java.util.ArrayList;
    import java.util.List;
    public class SaleTickets { public static void main(String[] args) {
    Tickets ts = new Tickets();
    ts.initTicket();
    SallThread st = new SallThread(ts);
    new Thread(st,"Thread1").start();
    new Thread(st,"Thread2").start();
    new Thread(st,"Thread3").start();
    new Thread(st,"Thread4").start();
    new Thread(st,"Thread5").start();
    }}class Ticket{
    private  int id;
    Ticket(int id) {
    this.id = id;
    }
    public int getId(){
    return id;
    }
    }
    class Tickets{
    List<Ticket> lt = new ArrayList<Ticket>();
    public void initTicket(){
    for(int i=0;i<100;i++){
    Ticket t = new Ticket(i);
    lt.add(t);
    }
    }
    public synchronized Ticket sall(){
    if(!lt.isEmpty()){
    return lt.remove((int)Math.random()*(lt.size()-1));
    }
    else return null;
    }
    }
    class SallThread implements Runnable{
    Tickets ts = null;
    SallThread(Tickets ts){
    this.ts = ts;
    }
    @Override
    public void run() {
    Ticket t = null;
    while(true) {
    if(ts.lt.size()>0) {
    t = ts.sall();
    System.out.println(Thread.currentThread().getName()+
    " sale a ticket which its id is" + t.getId() );
    }else {
    System.out.println(Thread.currentThread().getName()+" sale out!");
    break;
    }
    }
    }
    }
      

  12.   

    只要创建5个进程(Thread),然后共享一个类对象(Runnable),然后把100张火车票(编号和票数做同样处理,编号初值20000,卖一张 就减1)运用while循环表示出来,这又怎么实现随机卖票(线程决定)
      

  13.   

    你的5个线程的优先级都是一样的。所以每一个线程都是随机被CPU分配资源的,而且执行
    也是不确定的。
      

  14.   

    贴个代码
    public class TestTicket { public static void main(String[] args) {
    Ticket r = new Ticket();
    Thread t1 = new Thread(r,"窗口1");
    Thread t2 = new Thread(r,"窗口2");
    Thread t3 = new Thread(r,"窗口3");
    Thread t4 = new Thread(r,"窗口4");
    Thread t5 = new Thread(r,"窗口5");

    t1.start();
    t2.start();
    t3.start();
    t4.start();
    t5.start();
    }
    }class Ticket implements Runnable{
    private int tickets = 100;
    private int id = 20000000;
    @Override
    public  void run() {
    int j = 0;
    for (int i=0;i<100;i++){
    synchronized(this){
    if(tickets > 0){
    System.out.println(Thread.currentThread().getName() + "卖了" +"编号" + id );
    tickets--;
    id--;
    j++;
    }
    else break;
    try {
    Thread.sleep(50);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    System.out.println(Thread.currentThread().getName() +  " 共卖票数:" +j);
    }
    }