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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© vipzh 中级黑马   /  2013-3-13 22:33  /  2407 人查看  /  10 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张号 于 2013-3-15 12:04 编辑

创建了6个线程,同步后为什么总是只有一个线程在走?
  1. /售票窗口
  2. public class SealWindow
  3. {
  4.         public static void main(String[] args)
  5.         {
  6.                 new Thread(new TicketSealCenter(), "1号窗口").start();
  7.                 new Thread(new TicketSealCenter(), "2号窗口").start();
  8.                 new Thread(new TicketSealCenter(), "3号窗口").start();
  9.                 new Thread(new TicketSealCenter(), "4号窗口").start();
  10.                 new Thread(new TicketSealCenter(), "5号窗口").start();
  11.                 new Thread(new TicketSealCenter(), "6号窗口").start();

  12.         }

  13. }

  14. // 售票中心
  15. class TicketSealCenter implements Runnable
  16. {

  17.         private void sale() throws Exception
  18.         {
  19.                 Ticket ticket = new Ticket();
  20.                 // 售票中心分配火车票
  21.                 ticket.setTicketNum(100);

  22.                 while (ticket.isEmple())
  23.                 {
  24.         
  25.                         System.out.println(Thread.currentThread().getName() + "售出一张"
  26.                                         + "还剩下" + ticket.getTicketNum() + "张票");
  27.                         
  28.                         if (ticket.getTicketNum() == 0)
  29.                         {
  30.                                 System.out.println("票已经卖完了,明天再来吧!!!");
  31.                         }

  32.                 }
  33.         }

  34.         @Override
  35.         public void run()
  36.         {
  37.                 try
  38.                 {
  39.                         synchronized (TicketSealCenter.class)
  40.                         {
  41.                                 
  42.                                 sale();
  43.                         }

  44.                 }
  45.                 catch (Exception e)
  46.                 {
  47.                         e.printStackTrace();
  48.                 }
  49.         }
  50. }

  51. // 火车票类
  52. class Ticket
  53. {

  54.         private int ticketNum; // 火车票张数

  55.         // 获得火车票的数量
  56.         public int getTicketNum()
  57.         {
  58.                 return ticketNum;
  59.         }

  60.         // 设置火车票数量
  61.         public void setTicketNum(int ticketNum)
  62.         {
  63.                 this.ticketNum = ticketNum;
  64.         }

  65.         // 判断是否有票
  66.         public  boolean isEmple() throws Exception
  67.         {

  68.                 if (ticketNum > 0)
  69.                 {

  70.                         ticketNum--;
  71.                         Thread.sleep(1000);
  72.                         return true;
  73.                 }
  74.                 else
  75.                 {
  76.                         System.exit(0);
  77.                         return false;
  78.                 }
  79.         }

  80. }
复制代码

点评

如果问题已经解决了,请将分类改为已解决;一定要对别人的回答有相应的回复哦,谢谢  发表于 2013-3-15 08:23

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

10 个回复

倒序浏览
[ 本帖最后由 csatshell 于 2013-3-13 22:49 编辑 ]\n\n兄弟,你的程序运行后,只有1号窗口买票,原因是你的同步代码块的锁选择的问题 看如下代码(更改你的锁标志)

                                        //售票窗口
public class SealWindow
{
        public static void main(String[] args)
        {
                new Thread(new TicketSealCenter(), "1号窗口").start();
                new Thread(new TicketSealCenter(), "2号窗口").start();
                new Thread(new TicketSealCenter(), "3号窗口").start();
                new Thread(new TicketSealCenter(), "4号窗口").start();
                new Thread(new TicketSealCenter(), "5号窗口").start();
                new Thread(new TicketSealCenter(), "6号窗口").start();        }}// 售票中心
class TicketSealCenter implements Runnable
{        private void sale() throws Exception
        {
                Ticket ticket = new Ticket();
                // 售票中心分配火车票
                ticket.setTicketNum(100);                while (ticket.isEmple())
                {
        
                        System.out.println(Thread.currentThread().getName() + "售出一张"
                                        + "还剩下" + ticket.getTicketNum() + "张票");
                        
                        if (ticket.getTicketNum() == 0)
                        {
                                System.out.println("票已经卖完了,明天再来吧!!!");
                        }                }
        }        //@Override
  Object obj=new Object();//添加的
        public void run()
        {
                try
                {
                        synchronized (obj)
                        {
                                
                                sale();
                        }                }
                catch (Exception e)
                {
                        e.printStackTrace();
                }
        }
}// 火车票类
class Ticket
{        private int ticketNum; // 火车票张数        // 获得火车票的数量
        public int getTicketNum()
        {
                return ticketNum;
        }        // 设置火车票数量
        public void setTicketNum(int ticketNum)
        {
                this.ticketNum = ticketNum;
        }        // 判断是否有票
        public  boolean isEmple() throws Exception
        {                if (ticketNum > 0)
                {                        ticketNum--;
                        Thread.sleep(1);
                        return true;
                }
                else
                {
                        System.exit(0);
                        return false;
                }
        }}
                 

d.jpg (63.36 KB, 下载次数: 25)

d.jpg
回复 使用道具 举报
本帖最后由 张栓紧 于 2013-3-13 23:00 编辑
  1. public class SealWindow
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 new Thread(new TicketSealCenter(), "1号窗口").start();
  6.                 new Thread(new TicketSealCenter(), "2号窗口").start();
  7.                 new Thread(new TicketSealCenter(), "3号窗口").start();
  8.                 new Thread(new TicketSealCenter(), "4号窗口").start();
  9.                 new Thread(new TicketSealCenter(), "5号窗口").start();
  10.                 new Thread(new TicketSealCenter(), "6号窗口").start();

  11.         }

  12. }

  13. // 售票中心
  14. class TicketSealCenter implements Runnable
  15. {
  16.          
  17.        // 售票中心分配火车票
  18.       

  19.         private void sale() throws Exception
  20.         {
  21.                  Ticket ticket = new Ticket();
  22.                     ticket.setTicketNum(10);

  23.                 while (ticket.isEmple())
  24.                 {
  25.         
  26.                         System.out.println(Thread.currentThread().getName() + "售出一张"
  27.                                         + "还剩下" + ticket.getTicketNum() + "张票");
  28.                         
  29.                         if (ticket.getTicketNum() == 0)
  30.                         {
  31.                                 System.out.println("票已经卖完了,明天再来吧!!!");
  32.                         }

  33.                 }
  34.         }

  35.         @Override
  36.         public void run()
  37.         {
  38.                 try
  39.                 {
  40.                         synchronized (this)
  41.                         {
  42.                                 
  43.                                 sale();
  44.                         }

  45.                 }
  46.                 catch (Exception e)
  47.                 {
  48.                         e.printStackTrace();
  49.                 }
  50.         }
  51. }

  52. // 火车票类
  53. class Ticket
  54. {

  55.         private int ticketNum; // 火车票张数

  56.         // 获得火车票的数量
  57.         public int getTicketNum()
  58.         {
  59.                 return ticketNum;
  60.         }

  61.         // 设置火车票数量
  62.         public void setTicketNum(int ticketNum)
  63.         {
  64.                 this.ticketNum = ticketNum;
  65.         }

  66.         // 判断是否有票
  67.         public  boolean isEmple() throws Exception
  68.         {

  69.                 if (ticketNum > 0)
  70.                 {

  71.                         ticketNum--;
  72.                         Thread.sleep(1000);
  73.                         return true;
  74.                 }
  75.                 else
  76.                 {
  77.                         System.exit(0);
  78.                         return false;
  79.                 }
  80.         }

  81. }
复制代码
你把TicketSealCenter类锁死了,所以就只是一个线程在运行

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
失眠了,半夜来论坛逛下,我修改了下并测试了下代码,至少是能保证安全问题,肯定是可以优化的,明天有空的话我再来看看,希望别的同学帮着优化下
  1. package com.itheima;

  2. public class Test11
  3. {
  4.         public static void main(String[] args)
  5.         {
  6.                 [color=Red]Ticket1 ticket = new Ticket1(100);//初始化票的数量[/color]               
  7. new Thread(new TicketSealCenter1(ticket), "1号窗口").start();
  8.                 new Thread(new TicketSealCenter1(ticket), "2号窗口").start();
  9.                 new Thread(new TicketSealCenter1(ticket), "3号窗口").start();
  10.                 new Thread(new TicketSealCenter1(ticket), "4号窗口").start();
  11.                 new Thread(new TicketSealCenter1(ticket), "5号窗口").start();
  12.                 new Thread(new TicketSealCenter1(ticket), "6号窗口").start();

  13.         }

  14. }

  15. // 售票中心
  16. class TicketSealCenter1 implements Runnable
  17. {
  18.          
  19.        // 售票中心分配火车票
  20.       
  21.       [color=Red]private Ticket1 ticket;//Ticket对象最好定义在成员位置上[/color]
  22.         //ticket.setTicketNum(100);
  23.         TicketSealCenter1(Ticket1 ticket){
  24.                 this.ticket = ticket;
  25.         }
  26.       
  27.         private void sale() throws Exception
  28.         {
  29.                  //Ticket1 ticket = new Ticket1();
  30.                   // ticket.setTicketNum(100);
  31.                        
  32.                 while (ticket.isEmple())
  33.                 {
  34.                         [color=Red]int count = ticket.getTicketNum();//定义临时变量,记录票的数量[/color]                       
  35.                                         System.out.println(Thread.currentThread().getName()
  36.                                                         + "售出一张" + "还剩下" + count
  37.                                                         + "张票");
  38.                         
  39.                                         if (count == 0) {
  40.                                                 System.out.println("票已经卖完了,明天再来吧!!!");
  41.                                         }
  42.                 }
  43.         }

  44.         @Override
  45.         public void run()
  46.         {
  47.                 try
  48.                 {
  49.                         [color=Red]synchronized (this)//方法的锁最好定义为调用者this[/color]                        {
  50.                                 
  51.                                 sale();
  52.                         }

  53.                 }
  54.                 catch (Exception e)
  55.                 {
  56.                         e.printStackTrace();
  57.                 }
  58.         }
  59. }

  60. // 火车票类
  61. class Ticket1
  62. {

  63.         private int ticketNum = 100; // 火车票张数
  64.         Ticket1(int ticketNum){
  65.                 this.ticketNum = ticketNum;
  66.         }

  67.         // 获得火车票的数量
  68.         [color=Red]public synchronized int getTicketNum()//被多条线程操作的数据,要加同步[/color]        {
  69.                 return --ticketNum;
  70.         }

  71.         // 设置火车票数量
  72.         public void setTicketNum(int ticketNum)
  73.         {
  74.                 this.ticketNum = ticketNum;
  75.         }

  76.         // 判断是否有票
  77.        [color=Red] public synchronized boolean isEmple() throws Exception//被多条线程操作的数据,要加同步[/color]        {

  78.                 if (ticketNum > 0)
  79.                 {

  80.                                
  81.                         Thread.sleep(1000);
  82.                         return true;
  83.                 }
  84.                 else
  85.                 {
  86.                         System.exit(0);
  87.                         return false;
  88.                 }
  89.         }

  90. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
我去,论坛还玩儿不转,怎么设置注释的字体啊??{:soso_e127:}
回复 使用道具 举报
本帖最后由 李辉 于 2013-3-14 02:16 编辑

这里的问题不少啊!
第一点:最重要的也是最根本的问题是对多线程共享资源的不理解!除了李志阳,前几位创建的线程完全没有共享资源,每个线程都独立的拥有100张票(有一个人定义了10张),我要在这里说清楚恐怕得写太多。大家自己先好好学学。
第二点:类名。包含主函数的类才应该叫“TicketSealCenter“ 因为是这个类运行的时候创建了多个线程并且在调度这些线程,每个线程代表一个售票窗口。实现Runnable接口的类应该叫“SealWindow”。类名不单单是个单词,它代表着你对售票模型以及面向对象的理解。
第三点:同步的理解。同步是防止一个线程对共享数据操作一半的时候另一个线程开始操作。前几位都没有共享数据,同步只能起到一个作用:就是降低程序运行速度。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
0.00 中级黑马 2013-3-14 04:57:34
7#
表示弄了很久还是没弄好,起床再搞了,困死了 都天亮了,
你代码存在很多问题,正如楼上所说,锁只是锁共享的数据,而数据只有票在变,要锁住票, 还有一个就是 多线程不能像你那样传对象,那样的对象是独立的线程了,
需要同时传同一个对象进去!
回复 使用道具 举报
filter 中级黑马 2013-3-14 09:58:38
8#
楼上说的很到位,给你提供了思路,具体问题还是你自己解决吧,另外我多线程学的也不是很好,最后加的锁是嵌套的死锁,只卖几百张票可能还行,多了就出大问题了
,可能跟设计的方法有关吧
晚上再来看下
回复 使用道具 举报
0.00 中级黑马 2013-3-14 19:20:02
9#
public class SaleWindow
{
       public static void main(String[] args)
     {
                Thread t1=new Thread(new TicketSealCenter("1号窗口"));
                Thread t2=new Thread(new TicketSealCenter("2号窗口"));
                Thread t3=new Thread(new TicketSealCenter("3号窗口"));
                Thread t4=new Thread(new TicketSealCenter("4号窗口"));
                Thread t5=new Thread(new TicketSealCenter("5号窗口"));
                Thread t6=new Thread(new TicketSealCenter("6号窗口"));
                t1.start();t2.start();t3.start();t4.start();t5.start();t6.start();
               
                System.out.println("关门下班");
        }
}
//新建一个类
class  TicketSealCenter implements Runnable
{      
        private String iname;
       
        private static int inumber=100;
       
        Object o=new Object();
       
        public  void run()
    {
                if(inumber>0)
          { while(true)
                        {
                synchronized (o)
            {
                if(inumber>0)
                        {
                         System.out.println(this.getIname()+"火车票卖出一张,"+"剩余"+--inumber+"张.");
                         try
                            {Thread.sleep(1);}
                         catch (Exception e)
                                {System.out.println("系统异常");}
                        } else
                  break;
                        }
                       
                       
            }
         
         }
          
          }       
                       
       
       
        public String getIname()
          {
        return iname;
          }
        TicketSealCenter(String iname)
          {
         this.iname=iname;
          }
       
}
你试试这个代码

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
0.00 中级黑马 2013-3-14 19:23:03
10#
还是没锁住,坐等大神出现
回复 使用道具 举报
0.00 中级黑马 2013-3-14 20:34:15
11#
把锁的对象改为 类名.class,否则不是同一个锁
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马