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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张聪珉 中级黑马   /  2013-9-3 16:36  /  1739 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张聪珉 于 2019-9-11 14:14 编辑

sdfsdfsdfsdfsdfsdf

评分

参与人数 1技术分 +1 收起 理由
黄兴旺 + 1

查看全部评分

7 个回复

倒序浏览
这样做的结果就是同样的票卖了三次,一共三百张
回复 使用道具 举报
为什么不写注释- - 看不懂啊
回复 使用道具 举报
薛淑凯 发表于 2013-9-3 21:59
这样做的结果就是同样的票卖了三次,一共三百张

哥们,那我应该怎么实现啊,加同步代码块,求您知道,要是可以加上代码解析就万分感谢了
回复 使用道具 举报
张聪珉 发表于 2013-9-3 23:22
哥们,那我应该怎么实现啊,加同步代码块,求您知道,要是可以加上代码解析就万分感谢了
...

多个线程共享同一个数据,要么使用同一个Runnable对象,要么将这个共享数据进行封装然后加锁访问。修改后的代码

  1. //package com.itheima;

  2. import java.util.ArrayList;
  3. import java.util.Collections;

  4. /*5、  编写三各类Ticket、SealWindow、TicketSealCenter分别代表票信息
  5. * 、售票窗口、售票中心。售票中心分配一定数量的票,由若干个售票窗口进行出售,
  6. * 利用你所学的线程知识来模拟此售票过程。
  7. *
  8. * 需求分析:Ticket包含有票名和票号
  9. * TicketSealCenter是唯一的采用单例模式设计,有makeTickets生产票方法,和putTickets分配票方法
  10. * SealWindow实现Runnable接口,覆盖run方法,构造函数接受String窗口名称以及Ticket[] tickets票数
  11. */
  12. public class Test5 {

  13.         /**
  14.          * @param args
  15.          */
  16.         public static void main(String[] args) {
  17.                 // TODO Auto-generated method stub
  18.                 TicketSealCenter tsl=TicketSealCenter.getInstance();
  19.                 tsl.makeTickets("上海---北京", 100);
  20.                 Ticket[] tickets=tsl.putTickets();
  21.                 //创建三个卖票窗口每个窗口分配100张票
  22.                 /*SealWindow sealWindow1=new SealWindow("1号窗口",tickets);        
  23.                 SealWindow sealWindow2=new SealWindow("2号窗口",tickets);        
  24.                 SealWindow sealWindow3=new SealWindow("3号窗口",tickets);        
  25.                 new Thread(sealWindow1).start();
  26.                 new Thread(sealWindow1).start();
  27.                 new Thread(sealWindow1).start();*///这种方式最简单,使用同一个窗口实例,run方法加锁就行了,其他不需要修改
  28.                
  29.                 SealWindow sealWindow1=new SealWindow("1号窗口",tsl);        
  30.                 SealWindow sealWindow2=new SealWindow("2号窗口",tsl);        
  31.                 SealWindow sealWindow3=new SealWindow("3号窗口",tsl);
  32.                 new Thread(sealWindow1).start();
  33.                 new Thread(sealWindow2).start();
  34.                 new Thread(sealWindow3).start();//这种方式把共享数据封装访问,参数改成售票中心,每卖出一张票
  35.                                                                                 //售票中心里的票就少一张,以此类推
  36.         }

  37. }
  38. class SealWindow implements Runnable{
  39.         private String windowName;
  40.         //private Ticket[] tickets;
  41.         
  42.                 private TicketSealCenter tsc=null;
  43.         public SealWindow(String windowName,TicketSealCenter tsc){
  44.                 this.windowName=windowName;
  45.                 //this.tickets=tickets;
  46.                 this.tsc=tsc;
  47.         }
  48.         @Override
  49.         public void run() {
  50.                 /*for(int i=0;i<tickets.length;i++){
  51.                         tickets[i].setId(id--);
  52.                         try {
  53.                                 Thread.sleep(100);
  54.                         } catch (InterruptedException e) {
  55.                         }
  56.                         System.out.println(windowName+"卖出了:"+tickets[i]);
  57.                 }*/
  58.                 while(tsc.isEnd()){
  59.                         synchronized (tsc) {//这个锁保证原子性,避免出现打印语句后被挂起的错误
  60.                                         System.out.print(windowName);
  61.                                         tsc.sellTicket();
  62.                                 }
  63.                                 try {
  64.                     Thread.sleep(10);
  65.                         } catch (InterruptedException e) {
  66.                         }
  67.                        
  68.                 }
  69.                 System.out.println("车票售罄");
  70.         }
  71. }
  72. class TicketSealCenter{
  73.     private TicketSealCenter(){}
  74.     private static  TicketSealCenter tsl = new TicketSealCenter();
  75.     public static TicketSealCenter getInstance() {
  76.             return tsl;
  77.     }
  78.     private String ticketName;
  79.     private int number;
  80.     private Ticket[] tickets;
  81.     public void makeTickets(String ticketName,int number){
  82.              ArrayList<Ticket> al= new ArrayList<Ticket>();
  83.              //tickets=new Ticket[number];
  84.              for(int i=1;i<=number;i++){
  85.                      Ticket ticket=new Ticket(ticketName,i);
  86.                      al.add(ticket);
  87.                      tickets=al.toArray(new Ticket[al.size()]);
  88.              }
  89.     }
  90.     public Ticket[] putTickets(){
  91.             return tickets;
  92.     }
  93.     private int i=0;
  94.     public synchronized void sellTicket(){//定义的售票方法,需要加锁
  95.             if(i<tickets.length){
  96.                     int ticketNum=i+1;
  97.                     System.out.println("卖出了"+ ticketNum +"号票");
  98.                     tickets[i]=null;
  99.                     i++;
  100.             }
  101.     }
  102.    
  103.     public boolean isEnd(){//判断是否售罄
  104.             if(i>=tickets.length)
  105.                     return false;
  106.             return true;
  107.     }
  108.         
  109. }
  110. class Ticket {

  111.     public String getName() {
  112.                 return name;
  113.         }

  114.         public void setName(String name) {
  115.                 this.name = name;
  116.         }

  117.         public int getId() {
  118.                 return id;
  119.         }

  120.         public void setId(int id) {
  121.                 this.id = id;
  122.         }

  123.         private String name;

  124.     private int id ;
  125.     Ticket(String name, int id) {

  126.             this.name = name;

  127.             this.id = id;

  128.     }

  129.     public String toString() {
  130.             return this.name + "......" + this.id;
  131.     }



  132. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
杨增坤 + 1

查看全部评分

回复 使用道具 举报
薛淑凯 发表于 2013-9-4 11:25
多个线程共享同一个数据,要么使用同一个Runnable对象,要么将这个共享数据进行封装然后加锁访问。修改后 ...

谢谢哈,哥们你的代码比我的号,我有写了一次,还是没用使用同步但是感觉有漏洞,再看看哈
  1. package com.itheima;
  2. /*第5题:  编写三各类Ticket、SealWindow、TicketSealCenter分别代表票信息
  3. * 、售票窗口、售票中心。售票中心分配一定数量的票,由若干个售票窗口进行出售,
  4. * 利用你所学的线程知识来模拟此售票过程。
  5. *
  6. * 需求分析:Ticket包含有票名和票号,String name和int id
  7. * TicketSealCenter是唯一的,采用单例模式设计,有makeTickets生产票方法其接收三个参数分别是票名、票数、以及票号,
  8. * 和putTickets分配票方法。
  9. * SealWindow实现Runnable接口,覆盖run方法,构造函数接受String窗口名称以及Ticket[] tickets票数
  10. */
  11. import java.util.ArrayList;

  12. public class Test5 {

  13.         /**
  14.          * @param args
  15.          */
  16.         public static void main(String[] args) {
  17.                 // TODO Auto-generated method stub
  18.                 TicketSealCenter tsl=TicketSealCenter.getInstance();
  19.                 //生产100张编号从1开始的"上海---北京"的票
  20.                 tsl.makeTickets("上海---北京", 100,1);
  21.                 //获取编号从1开始的"上海---北京"的100张票
  22.                 Ticket[] tickets1=tsl.putTickets();
  23.                
  24.                 //生产100张编号从101开始的"上海---北京"的票
  25.                 tsl.makeTickets("上海---北京", 100,101);
  26.                 //获取编号从101开始的"上海---北京"的100张票
  27.                 Ticket[] tickets2=tsl.putTickets();
  28.                
  29.                 //生产100张编号从201开始的"上海---北京"的票
  30.                 tsl.makeTickets("上海---北京", 100,201);
  31.                 //获取编号从201开始的"上海---北京"的100张票
  32.                 Ticket[] tickets3=tsl.putTickets();
  33.                
  34.                 //创建三个卖票窗口每个窗口分配100张票
  35.                 SealWindow sealWindow1=new SealWindow("1号窗口",tickets1);       
  36.                 SealWindow sealWindow2=new SealWindow("2号窗口",tickets2);       
  37.                 SealWindow sealWindow3=new SealWindow("3号窗口",tickets3);
  38.                 //开启三个窗口线程开始卖票
  39.                 new Thread(sealWindow1).start();
  40.                 new Thread(sealWindow2).start();
  41.                 new Thread(sealWindow3).start();
  42.         }

  43. }
  44. class SealWindow implements Runnable{
  45.         private String windowName;
  46.         private Ticket[] tickets;
  47.        
  48.         public SealWindow(String windowName,Ticket[] tickets){
  49.                 this.windowName=windowName;
  50.                 this.tickets=tickets;
  51.         }
  52.         @Override
  53.         public void run() {
  54.                 // TODO Auto-generated method stub
  55.                 // 获取每个窗口的总票数       
  56.                 int num=tickets.length;
  57.                 for(int i=0;i<tickets.length;i++){
  58.                
  59.                         //下面文档注释可有可无,只是为了更为直观的观看测试结果的准确性而写的代码
  60.                         /*try {
  61.                                 Thread.sleep(10);
  62.                         } catch (InterruptedException e) {
  63.                        
  64.                                 e.printStackTrace();
  65.                         }*/
  66.                         //此处创建一个StringBuilder是为了把剩余的票数放进字符串缓冲区里变成字符串打印出来,方便观看结果
  67.                         //当然,如果不需要获得剩余的票数,此处StringBuilder以及放进StringBuilder的数据都可以不写
  68.                         StringBuilder sb=new StringBuilder();
  69.                         sb.append(num-1);
  70.                         System.out.println(windowName+"卖出了一张  "+tickets[i]+"...剩下"+sb.toString()+"票");
  71.                         //清空缓冲区
  72.                         sb.delete(0, 1);
  73.                         //每卖一张票就减少一张票
  74.                         num=num-1;
  75.                 }
  76.                
  77.                 /*for(Ticket ticket:tickets)
  78.                         System.out.println(windowName+"卖出了:"+ticket);*/
  79.         }
  80.        
  81. }
  82. class TicketSealCenter{
  83.         private TicketSealCenter(){}
  84.         private static  TicketSealCenter tsl = new TicketSealCenter();
  85.     public static TicketSealCenter getInstance() {
  86.             return tsl;
  87.     }

  88.     private Ticket[] tickets;
  89.     //makeTickets方法接收三个参数分别是票名、票数、以及票号
  90.     public void makeTickets(String ticketName,int number,int id){
  91.              ArrayList<Ticket> al= new ArrayList<Ticket>();
  92.              //tickets=new Ticket[number];
  93.              for(int i=1;i<=number;i++){
  94.                      //遍历票数生产对应的票
  95.                      Ticket ticket=new Ticket(ticketName,id++);
  96.                      al.add(ticket);
  97.                      tickets=al.toArray(new Ticket[al.size()]);
  98.              }
  99.     }
  100.     public Ticket[] putTickets(){
  101.             return tickets;
  102.     }

  103.        
  104. }
  105. class Ticket {

  106.         private String name;
  107.        
  108.         private int id ;
  109.         Ticket(String name, int id) {
  110.                
  111.                 this.name = name;
  112.                
  113.                 this.id = id;
  114.                
  115.         }
  116.     public String getName() {
  117.                 return name;
  118.         }

  119.         public void setName(String name) {
  120.                 this.name = name;
  121.         }

  122.         public int getId() {
  123.                 return id;
  124.         }

  125.         public void setId(int id) {
  126.                 this.id = id;
  127.         }


  128.     public String toString() {
  129.             return this.name + "的票,票号为" + this.id;
  130.     }



  131. }
复制代码
回复 使用道具 举报
买票必须是多线程,使用线程同步技术。。。。。。

/*
* 卖票的实例
* 100张票,4个线程同时模拟卖票
*
*
  |-- 定义类,实现Runnable接口
  |-- 覆盖接口的抽象方法 run
  |-- 建立Thread对象,在Thread构造方法中,传递Runnable接口的实现类对象
  |-- 调用Thread对象start()方法
  
*/
class Ticket implements Runnable{
        private int tickets = 100;//定义100张抛
        public void run(){
                while(true){
                        if(tickets>0){
                                try{
                                        Thread.sleep(5);
                                }catch(InterruptedException e){}
                                System.out.println(Thread.currentThread().getName()+"卖出第。。。"+tickets--);
                        }
                }
        }
}
public class ThreadDemo1 {

        public static void main(String[] args) {
        //        public Thread(Runnable target)=new Ticket
                Ticket t = new Ticket();
                Thread t0 = new Thread(t);
                Thread t1 = new Thread(t);
                Thread t2 = new Thread(t);
                Thread t3 = new Thread(t);
               
                t0.start();
                t1.start();
                t2.start();
                t3.start();
        }

}

评分

参与人数 1技术分 +1 收起 理由
杨增坤 + 1

查看全部评分

回复 使用道具 举报
    synchronized  和 lock都可以锁住的
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马