A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© www851903307 中级黑马   /  2015-2-23 11:59  /  3350 人查看  /  10 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

编写三各类Ticket、SealWindow、TicketSealCenter分别代表票信息、售票窗口、售票中心。
        售票中心分配一定数量的票,由若干个售票窗口进行出售,利用你所学的线程知识来模拟此售票过程。
* @author Administrator
*
*/
public class TreadDemo {
        public static void main(String[] args) {
                Ticket t= new Ticket(100);
                SealWindow ss = new SealWindow(t);
                Thread t1 = new Thread(ss);
                Thread t2 = new Thread(ss);
                Thread t3 = new Thread(ss);
                t1.start();
                t2.start();
                t3.start();
        }
       
}
class Ticket {
       
        private int num;
        private boolean flag= false;
       
        public Ticket(int num) {
                super();
                this.num = num;
        }

        public synchronized void output(){
                while (!flag) {
                        if(num>0){
                                System.out.println(Thread.currentThread().getName()+"-----------"+num--);
                        }else{
                                flag = true;
                        }
                }               
        }
}
//售票窗口
class SealWindow implements Runnable{
        private Ticket ticket;

        public SealWindow(Ticket ticket) {
                super();
                this.ticket = ticket;
        }

        @Override
        public void run() {
                while (true) {
                        ticket.output();
                        try {
                                Thread.sleep(100);
                        } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                        }          
                }
        }
}
提问:我的程序线程没有切换,如何改变

评分

参与人数 1技术分 +1 收起 理由
lwj123 + 1

查看全部评分

10 个回复

倒序浏览
你这样不是只创建一个售票窗口而已吗?题目不是要求开四个售票窗口吗?

我觉得实际卖票的是售票中心提供的功能
而每个窗口的卖票是调用的是售票中心提供的功能
所以将每个窗口的对象传递给售票中心,表明此窗口在卖票。

回复 使用道具 举报
lwj123 发表于 2015-2-23 12:29
你这样不是只创建一个售票窗口而已吗?题目不是要求开四个售票窗口吗?

我觉得实际卖票的是售票中心提供的 ...

看的毕老师视频,类似于生产者、消费者的,票有卖的方法和产生票的方法,售票窗口调用卖的方法,售票中心有产生票的方法。。。我的问题是只有一个线程起作用,即使我产生三个窗口,但不会切换,请教咋解决啊
回复 使用道具 举报
我帮你修改了一下,我运行了下,我估计是你的while循环有问题,你发现没有你的事循环中再调用循环
修改代码:
import java.util.*;
public class TreadDemo {
     public static void main(String[] args) {
         Ticket t= new Ticket(1000);
         SealWindow s1 = new SealWindow(t);
         //SealWindow s2 = new SealWindow(t);
         //SealWindow s3 = new SealWindow(t);
         Thread t1 = new Thread(s1);
         Thread t2 = new Thread(s1);
         Thread t3 = new Thread(s1);
         t1.start();
         t2.start();
         t3.start();
     }
         
}
class Ticket
{
         
     private int num;
     private boolean flag= false;
     
     public Ticket(int num) {
             super();
             this.num = num;
     }

     public synchronized void output()
     {
         if(num>0)
         {
           System.out.println(Thread.currentThread().getName()+"-----------"+num--);
           try{Thread.sleep(50);}catch(InterruptedException e){}
           
         }            
     }
}
//售票窗口
class SealWindow implements Runnable
{
                 private Ticket ticket;
               
                 public SealWindow(Ticket ticket) {
                     super();
                     this.ticket = ticket;
                 }
               
                 @Override
                 public void run()
                 {
                     while(true)
                     {
                                ticket.output();
                     }
                 }
}
回复 使用道具 举报
  1. <div class="blockcode"><blockquote><div class="blockcode"><blockquote>package cn.itheima.demo;

  2. /**
  3. * 这是售票窗口
  4. *
  5. * @author pinger
  6. *
  7. */
  8. public class SealWindow {
  9.         public static void main(String[] args) {
  10.                 // 创建共享资源
  11.                 Ticket t = new Ticket();

  12.                 TicketSealCenter gt = new TicketSealCenter(t);

  13.                 // 设置线程
  14.                 Thread t1 = new Thread(gt, "窗口一");
  15.                 Thread t2 = new Thread(gt, "窗口二");
  16.                 Thread t3 = new Thread(gt, "窗口三");
  17.                 // 线程启动
  18.                 t1.start();
  19.                 t2.start();
  20.                 t3.start();
  21.         }
  22. }
复制代码

package cn.itheima.demo;

/**
* 这是售票中心
*
* @author pinger
*
*/
public class TicketSealCenter implements Runnable {
        // 设置构造,共享资源对象
        private Ticket t;

        public TicketSealCenter(Ticket t) {
                this.t = t;
        }

        @Override
        public void run() {

                while (true) {

                        synchronized (t) {
                                try {
                                        Thread.sleep(100);
                                } catch (InterruptedException e) {
                                        e.printStackTrace();
                                }
                                // 消费资源
                                Ticket.sellTicket();
                        }

                }
        }

}

package cn.itheima.demo;

/**
* 这是一个票的基本信息的类
*
* @author pinger
*
*/
public class Ticket {
        // 票信息
        private static int tickets = 100;

        // 售票的方式
        public static void sellTicket() {

                if (tickets > 0) {
                        // 进行消费
                        System.out.println(Thread.currentThread().getName() + "正在售"
                                        + Ticket.tickets-- + "张票");

                }
        }
}




回复 使用道具 举报
liaohongjie 发表于 2015-2-23 16:17
我帮你修改了一下,我运行了下,我估计是你的while循环有问题,你发现没有你的事循环中再调用循环
修改代码 ...

谢了 学习了
回复 使用道具 举报
万合天宜 发表于 2015-2-23 16:36
package cn.itheima.demo;

/**

恩恩 谢了
回复 使用道具 举报
锁的位置锁在了循环外面 也就是说一个线程进去后把门锁上然后自己狂循环做完了全部工作才把门打开,其它线程进来后发现活已经干完了,也就从始至终没干过活.
回复 使用道具 举报
liaohongjie 发表于 2015-2-23 16:17
我帮你修改了一下,我运行了下,我估计是你的while循环有问题,你发现没有你的事循环中再调用循环
修改代码 ...

你这个好像不对。

点评

哪里不对啊!  发表于 2015-2-24 17:35
回复 使用道具 举报
我的做法,同步方法放在售票中心类中。
  1. package com.itheima;

  2. /**
  3. *第6题:编写三个类Ticket、SealWindow、TicketSealCenter分别代表票信息、售票窗口、售票中心。
  4. * 售票中心分配一定数量的票,由若干个售票窗口进行出售,利用你所学的线程知识来模拟此售票过程。
  5. * @author zl
  6. *思路:多个线程访问同一个数据存储单元,需要同步。
  7. *详细:
  8. *一,定义票。每产生一个新票,其序号就自动增1,需要静态sid;类的成员变量为id(记录每个票的当前id)。
  9. *二,定义窗口。新增窗口自动产生id,故需要静态sid;需要指定其拿票的中心;重写run方法,有票就拿。
  10. *三,定义中心。中心必须有装票的容器或数组;指定当前可取的票;同步被拿走票和产生票的方法。
  11. */
  12. public class Test06_Synchronized {

  13.         public static void main(String[] args) {
  14.                 // 定义TicketSealCenter和SealWindow实例
  15.                 TicketSealCenter tsc = new TicketSealCenter();
  16.                 tsc.put(30);
  17.                 SealWindow sw1 = new SealWindow(tsc);
  18.                 SealWindow sw2 = new SealWindow(tsc);
  19.                 SealWindow sw3 = new SealWindow(tsc);
  20.                
  21.                 //定义多个线程
  22.                 new Thread(sw1).start();
  23.                 new Thread(sw2).start();
  24.                 new Thread(sw3).start();
  25.         }
  26. }
  27. /*
  28. * 定义Ticket类;
  29. * 属性包括:Ticket的id
  30. * 需要构造方法;
  31. * 需要id的set和get方法
  32. */
  33. class Ticket {
  34.         //Ticket的序号
  35.         private int id;
  36.         //定义一个静态变量,记录下一个新产生的票的序号
  37.         private static int sid = 1;       
  38.        
  39.         //构造方法
  40.         Ticket() {
  41.                 this.setId(sid);
  42.                 sid ++;
  43.         }
  44.        
  45.         //定义set和get方法
  46.         public int getId() {
  47.                 return id;
  48.         }
  49.         public void setId(int id) {
  50.                 this.id = id;
  51.         }
  52. }

  53. /*
  54. * 定义SealWindow类,实现Runnable以开启新的线程
  55. * 属性:SealWindow的id,与之联系的TicketSealCenter对象
  56. * 构造方法:每增加一个SealWindow,id加1;参数包括特定的TicketSealCenter对象
  57. * 重写run方法
  58. */
  59. class SealWindow implements Runnable {
  60.         //定义SealWindow的id号
  61.         private int id;
  62.         //定义静态变量,自动记录下一个新产生的的SealWindow序号
  63.         private static int sid = 1;
  64.         //定义对应的TicketSealCenter,即该SealWindow向哪个TicketSealCenter拿票
  65.         private TicketSealCenter tsc;

  66.         //构造方法
  67.         SealWindow(TicketSealCenter tsc) {
  68.                 this.setId(sid);
  69.                 //每新创建一个SealWindow实例,就自动记录下一个新产生的的SealWindow序号,方便
  70.                 sid ++;
  71.                 this.tsc = tsc;
  72.         }

  73.         //重写run方法
  74.         public void run() {
  75.                 // 若TicketSealCenter有票,该窗口就每隔一段时间拿一张Ticket
  76.                 while(tsc.getIndex()>0) {
  77.                         tsc.pop(this.id);
  78.                         try {
  79.                                 Thread.sleep((int)(Math.random()*200));
  80.                         } catch (InterruptedException e) {
  81.                                 e.printStackTrace();
  82.                         }
  83.                 }       
  84.         }

  85.         //定义set和get方法
  86.         public int getId() {
  87.                 return id;
  88.         }
  89.         public void setId(int id) {
  90.                 this.id = id;
  91.         }
  92. }

  93. /*
  94. * 定义TicketSealCenter类
  95. * 属性:Ticket数组,以及当前空票的指针
  96. * 构造方法:初始化Ticket容器的方法
  97. * 拿和产生Ticket的方法需要同步
  98. */
  99. class TicketSealCenter {
  100.         //定义Ticket数组和下一张空票的指针
  101.         Ticket[] ts = new Ticket[100];
  102.         int index = 0;

  103.         //定义拿票的方法,需要同步
  104.         synchronized public Ticket pop(int sealWindowId) {
  105.                 // 执行一次,先判断是否拿完,若有票则index--,否则返回null
  106.                 if(index>0) {
  107.                         //拿出票后,index指针往前移动一个单元
  108.                         index --;
  109.                         //获取拿出的票的信息
  110.                         Ticket t = ts[index];
  111.                         //打印拿票的信息,打印信息需要在此处打印为好;若在SealWindow类中的run方法里打印,则会导致拿票和打印信息两动作不同步
  112.                         System.out.println( "窗口" + sealWindowId + ":拿出" + t.getId() + "号票");
  113.                         return t;
  114.                 }
  115.                 //没有票就返回空
  116.                 return null;       
  117.         }

  118.         //定义产生票的方法,需要同步
  119.         synchronized public void put(int tikNum) {
  120.                 if(index==0) {
  121.                         for(int i=0; i<tikNum; i++) {
  122.                                 this.ts[i] = new Ticket();
  123.                                 index ++;
  124.                         }
  125.                 }
  126.         }

  127.         //定义get和set方法
  128.         public int getIndex() {
  129.                 return index;
  130.         }
  131.         public void setIndex(int index) {
  132.                 this.index = index;
  133.         }
  134. }
复制代码
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马