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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 徐升2013 于 2013-4-15 17:03 编辑
  1. /*7、 编写三各类Ticket、SealWindow、TicketSealCenter分别代表票信息、售票窗口、售票中心。
  2. * 售票中心分配一定数量的票,由若干个售票窗口进行出售,利用你所学的线程知识来模拟此售票过程。
  3. *
  4. *
  5. */
  6. public class Test7 {
  7.         public static void main(String[] args) {
  8.                 Prodrucer p1 = new Prodrucer("北京--上海", 1);
  9.                 SealWindow s1 = new SealWindow();

  10.                 Thread t1 = new Thread(p1, "生产者1");
  11.                 Thread t2 = new Thread(p1, "生产者2");
  12.                 Thread t3 = new Thread(s1, "售票窗口1");
  13.                 Thread t4 = new Thread(s1, "售票窗口2");
  14.                 Thread t5 = new Thread(s1, "售票窗口3");

  15.                 t1.start();
  16.                 t2.start();
  17.                 t3.start();
  18.                 t4.start();
  19.                 t5.start();

  20.         }
  21. }

  22. class SealWindow implements Runnable {

  23.         private TicketSealCenter tt = null;

  24.         SealWindow() {
  25.                 tt = TicketSealCenter.getInstance();

  26.         }

  27.         @Override
  28.         public void run() {
  29.                 tt.put();

  30.         }
  31. }

  32. class Prodrucer implements Runnable {
  33.         private TicketSealCenter tt = null;
  34.         private Ticket t = null;

  35.         Prodrucer(String name, int ID) {
  36.                 t = Ticket.getInstance();
  37.                 tt = TicketSealCenter.getInstance();
  38.                 t.setId(ID);
  39.                 t.setName(name);
  40.         }

  41.         @Override
  42.         public void run() {
  43.                 tt.make();

  44.         }
  45. }

  46. class TicketSealCenter {
  47.         private Ticket t = null;
  48.         private boolean flag = false;
  49.         private Lock lock = new ReentrantLock();
  50.         private Condition m = lock.newCondition();
  51.         private Condition p = lock.newCondition();

  52.         private TicketSealCenter() {
  53.                 t = Ticket.getInstance();

  54.         }

  55.         private static final TicketSealCenter tt = new TicketSealCenter();

  56.         public static TicketSealCenter getInstance() {
  57.                 return tt;
  58.         }

  59.         public void make() {
  60.                 lock.lock();

  61.                 try {
  62.                         while (true) {
  63.                                 if (flag)
  64.                                         m.await();
  65.                                 System.out.println("生产了一张信息为:" + t.toString() + "的票.");
  66.                                 flag = true;
  67.                                 p.signal();
  68.                         }

  69.                 } catch (InterruptedException e) {
  70.                         e.printStackTrace();
  71.                 } finally {
  72.                         lock.unlock();
  73.                 }

  74.         }

  75.         public void put() {
  76.                 lock.lock();

  77.                 try {
  78.                         while (true) {
  79.                                 if (!flag)
  80.                                         p.await();
  81.                                 System.out.println("出售了一张:" + t.getName() + "的票,Id为:"
  82.                                                 + t.getId());
  83.                                 flag = false;
  84.                                 m.signal();
  85.                         }

  86.                 } catch (InterruptedException e) {
  87.                         e.printStackTrace();
  88.                 } finally {
  89.                         lock.unlock();
  90.                 }

  91.         }
  92. }

  93. class Ticket {
  94.         private String name;
  95.         private int id = 1;
  96.         private static final Ticket ticket = new Ticket("请设置票的名字", 1);

  97.         private Ticket(String name, int id) {
  98.                 this.name = name;
  99.                 this.id = id;
  100.         }

  101.         public static Ticket getInstance() {
  102.                 return ticket;
  103.         }

  104.         public String getName() {
  105.                 return name;
  106.         }

  107.         public void setName(String name) {
  108.                 this.name = name;
  109.         }

  110.         public int getId() {

  111.                 return id;
  112.         }

  113.         public void setId(int id) {
  114.                 this.id = id;
  115.         }

  116.         public String toString() {
  117.                 id++;
  118.                 return this.getName() + "......" + this.getId();
  119.         }

  120. }
复制代码
为什么加锁后还是会出现错号的现象呢?该怎么优化才可以?

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

5 个回复

倒序浏览
开始测了几次后出现了问题,以为是锁的对象不一致,后来发现不是
只是稍稍改动了一下,在if(flag)那加了{},后来又测试,没问题了,我一直在想是什么原因,可是想不明白,只有告诉自己,以后写if语句的时候安安生生加{}吧
楼主也可以想想原因,我也想知道为什么
  1. import java.util.concurrent.locks.Condition;
  2. import java.util.concurrent.locks.Lock;
  3. import java.util.concurrent.locks.ReentrantLock;

  4. /*7、 编写三各类Ticket、SealWindow、TicketSealCenter分别代表票信息、售票窗口、售票中心。

  5. * 售票中心分配一定数量的票,由若干个售票窗口进行出售,利用你所学的线程知识来模拟此售票过程。

  6. *
  7. *
  8. */

  9. public class Test7 {

  10.         public static void main(String[] args) {

  11.                 Prodrucer p1 = new Prodrucer("北京--上海", 0);

  12.                 SealWindow s1 = new SealWindow();


  13.                 Thread t1 = new Thread(p1, "生产者1");

  14.                 Thread t2 = new Thread(p1, "生产者2");

  15.                 Thread t3 = new Thread(s1, "售票窗口1");

  16.                 Thread t4 = new Thread(s1, "售票窗口2");

  17.                 Thread t5 = new Thread(s1, "售票窗口3");


  18.                 t1.start();

  19.                 t2.start();

  20.                 t3.start();

  21.                 t4.start();

  22.                 t5.start();


  23.         }

  24. }


  25. class SealWindow implements Runnable {


  26.         private TicketSealCenter tt = null;


  27.         SealWindow() {

  28.                 tt = TicketSealCenter.getInstance();


  29.         }


  30.         @Override

  31.         public void run() {
  32.                 //while(true){
  33.                 tt.put();

  34.                 //}
  35.         }

  36. }


  37. class Prodrucer implements Runnable {

  38.         private TicketSealCenter tt = null;

  39.         private Ticket t = null;


  40.         Prodrucer(String name, int ID) {

  41.                 t = Ticket.getInstance();

  42.                 tt = TicketSealCenter.getInstance();

  43.                 t.setId(ID);

  44.                 t.setName(name);

  45.         }

  46.         @Override

  47.         public void run() {
  48.                 //while(true){

  49.                 tt.make();
  50.                 //}

  51.         }

  52. }


  53. class TicketSealCenter {

  54.         private  static Ticket t = null;

  55.         private boolean flag = false;

  56.         private final Lock lock = new ReentrantLock();

  57.         private final Condition make = lock.newCondition();
  58.         
  59.      
  60.         private final Condition put = lock.newCondition();


  61.         private TicketSealCenter() {

  62.                t = Ticket.getInstance();


  63.         }


  64.         private static final TicketSealCenter tt = new TicketSealCenter();


  65.         public static TicketSealCenter getInstance() {

  66.                 return tt;

  67.         }

  68.         
  69.         public void make() {
  70.                   lock.lock();
  71.                
  72.                 try {
  73.                                 while(true){
  74.                                 if(flag){
  75.                                                                    make.await();//如果flag为真就让Prodrucer的两个线程等地待
  76.                                // System.out.println( lock.toString()+"make");开始查lock持有的对象用了
  77.                                 }
  78.                              else{
  79.                                 System.out.println(Thread.currentThread().getName()+": 生产了一张信息为:" + t.toString() + "的票.");

  80.                                 flag = true;

  81.                                 put.signal();//依次唤醒
  82.                                }//我想着是加了{}这段代码变成了一个语句。算了,不会解释了
  83.                          }
  84.                         } catch (InterruptedException e) {

  85.                         e.printStackTrace();

  86.                 } finally {

  87.                         lock.unlock();

  88.                 }


  89.         }

  90.         public void put() {

  91.                 lock.lock();
  92.             
  93.                 try {
  94.                                     while(true){  
  95.                                             if (!flag){
  96.                                                 put.await();//同上
  97.                                // System.out.println(  lock.toString()+"put");
  98.                                             }
  99.                                       else{
  100.                                 System.out.println(Thread.currentThread().getName()+": 出售了一张:" + t.getName() + "的票,Id为:"

  101.                                                 + t.getId());

  102.                                                 flag = false;
  103.                                                 make.signal();
  104.                               }
  105.                                   }

  106.                 } catch (InterruptedException e) {

  107.                         e.printStackTrace();

  108.                 } finally {

  109.                         lock.unlock();

  110.                 }


  111.         }

  112. }


  113. class Ticket {

  114.         private String name;

  115.         private int id = 0;

  116.         private static final Ticket ticket = new Ticket("请设置票的名字", 1);
  117.         private Ticket(String name, int id) {

  118.                 this.name = name;

  119.                 this.id = id;

  120.         }
  121.        public static Ticket getInstance() {

  122.                 return ticket;

  123.         }
  124.        public String getName() {

  125.                 return name;

  126.         }
  127.        public void setName(String name) {

  128.                 this.name = name;

  129.         }
  130.        public int getId() {


  131.                 return id;

  132.         }


  133.         public void setId(int id) {

  134.                 this.id = id;

  135.         }


  136.         public String toString() {
  137.                    id++;
  138.               return this.getName() + "......" + this.getId();
  139.                

  140.         }


  141. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
曹睿翔 发表于 2013-4-15 20:37
开始测了几次后出现了问题,以为是锁的对象不一致,后来发现不是
只是稍稍改动了一下,在if(flag)那加了{ ...

终于等到了一个回答 泪奔中。
回复 使用道具 举报
曹睿翔 发表于 2013-4-15 20:37
开始测了几次后出现了问题,以为是锁的对象不一致,后来发现不是
只是稍稍改动了一下,在if(flag)那加了{ ...

其实我一直怀疑原因是什么?难道是因为双核?
回复 使用道具 举报
徐升2013 发表于 2013-4-15 20:47
其实我一直怀疑原因是什么?难道是因为双核?

针对这个问题,我对老毕的一些代码也进行了测试- -也出现过此问题,需要多运行几次,并且至少2个生产者,二个消费者。
回复 使用道具 举报
徐升2013 发表于 2013-4-15 20:51
针对这个问题,我对老毕的一些代码也进行了测试- -也出现过此问题,需要多运行几次,并且至少2个生产者, ...

环境这时候重要了吧,要是在黑马那该多少牛人能帮到咱
你的心情我理解,没人回答确实很尴尬不爽啊,多线程这块是难点,张老师的多线程回顾是精品,我现在还没理解多少,加油啊!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马