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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Tesla时光 中级黑马   /  2012-9-7 21:48  /  2982 人查看  /  14 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 翁发达 于 2012-9-9 21:34 编辑

请注意:要求是在代码里和方法里都实现synchronized锁,每个线程都要运行,有好几位朋友帮我解答的都是一个线程执行到结尾.
如果是要这个结果,我的现在的代码都可以实现,一点问题也没有.我是要看到多个线程一起跑,且方法里,和方法上都有同步.
同步的是同一把锁,是不会锁死的,

请帮我看看问题出在哪?谢谢
public class SouPiao
{
public static void main(String[] args)
{
  Runnable r =new Sou();
  Thread  t =new Thread(r);
  Thread  t1 =new Thread(r);
  t.start();
  Sou.falg=false;
  t1.start();
}
}
class Sou implements Runnable
{
static boolean  falg =true;
private int a =100;
int count =1;//定义一个记数器,看最终是不是100张票.
public synchronized void sell()
{
  while(a>0)
  {
   if(a>0)
   {
    System.out.println(Thread.currentThread().getName()+":  "+a+"-----"+count++);
    try{Thread.sleep(10);}catch(Exception e){}
    a--;
   }
  }  
}
public  void run()
{
  if (falg)
  {
   while(a>0){
    synchronized(this)
    {
     if(a>0)
     {
      System.out.println(Thread.currentThread().getName()+":  "+a+"-----"+count++);
      try{Thread.sleep(10);}catch(Exception e){}
      a--;
     }
     
    }
   }
  }
  else
  {
   sell();
  }
}
}


14 个回复

倒序浏览
稍等一下哈!
回复 使用道具 举报
吕书凯 发表于 2012-9-7 22:12
楼上又占座

一不小心,让你发现了啊!{:soso_e113:}
回复 使用道具 举报
楼主你的代码逻辑错了,先看看你的main方法
  1. <blockquote><blockquote>public static void main(String[] args) {
复制代码
代码执行到 t.start()时,t这个线程启动,这时main方法继续执行把Sou的flat修改为false,这时t线程执行到run里的if (falg)语句,这个条件显然不成立,执行else里面的sell方法里,注意你的sell方法里面的逻辑
  1. while (a > 0) {
  2.     if (a > 0) {
  3.           System.out.println("sell" + Thread.currentThread().getName() + ": " + a
  4.               + "-----" + count++);
  5.           try {
  6.               Thread.sleep(10);
  7.            } catch (Exception e) { }
  8.            a--;
  9.     }
  10. }
复制代码
当执行这个代码时,一直把a搞成0才罢休。这个时候flat已经为flase,a为0,t和t1的run方法里面的if语句块是没有机会执行了,只能执行else语句块进入sell方法,a为0了sell方法执行也没意义了,所以程序就结束了。
把sell方法的打印语句改为
  1. System.out.println("sell " + Thread.currentThread().getName() + ": " + a
  2. + "-----" + count++);
复制代码
在运行下程序执行结果为:
  1. sell Thread-0: 100-----1
  2. sell Thread-0: 99-----2
  3. sell Thread-0: 98-----3
  4. sell Thread-0: 97-----4
  5. sell Thread-0: 96-----5
  6. sell Thread-0: 95-----6
  7. sell Thread-0: 94-----7
  8. sell Thread-0: 93-----8
  9. sell Thread-0: 92-----9
  10. sell Thread-0: 91-----10
  11. sell Thread-0: 90-----11
  12. sell Thread-0: 89-----12
  13. sell Thread-0: 88-----13
  14. sell Thread-0: 87-----14
  15. sell Thread-0: 86-----15
  16. sell Thread-0: 85-----16
  17. sell Thread-0: 84-----17
  18. sell Thread-0: 83-----18
  19. sell Thread-0: 82-----19
  20. sell Thread-0: 81-----20
  21. sell Thread-0: 80-----21
  22. sell Thread-0: 79-----22
  23. sell Thread-0: 78-----23
  24. sell Thread-0: 77-----24
  25. sell Thread-0: 76-----25
  26. sell Thread-0: 75-----26
  27. sell Thread-0: 74-----27
  28. sell Thread-0: 73-----28
  29. sell Thread-0: 72-----29
  30. sell Thread-0: 71-----30
  31. sell Thread-0: 70-----31
  32. sell Thread-0: 69-----32
  33. sell Thread-0: 68-----33
  34. sell Thread-0: 67-----34
  35. sell Thread-0: 66-----35
  36. sell Thread-0: 65-----36
  37. sell Thread-0: 64-----37
  38. sell Thread-0: 63-----38
  39. sell Thread-0: 62-----39
  40. sell Thread-0: 61-----40
  41. sell Thread-0: 60-----41
  42. sell Thread-0: 59-----42
  43. sell Thread-0: 58-----43
  44. sell Thread-0: 57-----44
  45. sell Thread-0: 56-----45
  46. sell Thread-0: 55-----46
  47. sell Thread-0: 54-----47
  48. sell Thread-0: 53-----48
  49. sell Thread-0: 52-----49
  50. sell Thread-0: 51-----50
  51. sell Thread-0: 50-----51
  52. sell Thread-0: 49-----52
  53. sell Thread-0: 48-----53
  54. sell Thread-0: 47-----54
  55. sell Thread-0: 46-----55
  56. sell Thread-0: 45-----56
  57. sell Thread-0: 44-----57
  58. sell Thread-0: 43-----58
  59. sell Thread-0: 42-----59
  60. sell Thread-0: 41-----60
  61. sell Thread-0: 40-----61
  62. sell Thread-0: 39-----62
  63. sell Thread-0: 38-----63
  64. sell Thread-0: 37-----64
  65. sell Thread-0: 36-----65
  66. sell Thread-0: 35-----66
  67. sell Thread-0: 34-----67
  68. sell Thread-0: 33-----68
  69. sell Thread-0: 32-----69
  70. sell Thread-0: 31-----70
  71. sell Thread-0: 30-----71
  72. sell Thread-0: 29-----72
  73. sell Thread-0: 28-----73
  74. sell Thread-0: 27-----74
  75. sell Thread-0: 26-----75
  76. sell Thread-0: 25-----76
  77. sell Thread-0: 24-----77
  78. sell Thread-0: 23-----78
  79. sell Thread-0: 22-----79
  80. sell Thread-0: 21-----80
  81. sell Thread-0: 20-----81
  82. sell Thread-0: 19-----82
  83. sell Thread-0: 18-----83
  84. sell Thread-0: 17-----84
  85. sell Thread-0: 16-----85
  86. sell Thread-0: 15-----86
  87. sell Thread-0: 14-----87
  88. sell Thread-0: 13-----88
  89. sell Thread-0: 12-----89
  90. sell Thread-0: 11-----90
  91. sell Thread-0: 10-----91
  92. sell Thread-0: 9-----92
  93. sell Thread-0: 8-----93
  94. sell Thread-0: 7-----94
  95. sell Thread-0: 6-----95
  96. sell Thread-0: 5-----96
  97. sell Thread-0: 4-----97
  98. sell Thread-0: 3-----98
  99. sell Thread-0: 2-----99
  100. sell Thread-0: 1-----100
复制代码
看到了吧,只有线程t执行了,并且只执行了sell方法
楼主在考虑下你代码的逻辑吧,不明白的话可以debug下,看看代码的执行


回复 使用道具 举报
{:soso_e135:},掉线了一会,被抢楼了,唉。。。。。。。移动无线伤不起啊
回复 使用道具 举报
public class SouPiao
{

public static void main(String[] args) {

                SaleCenter sc = new SaleCenter(100);
                SaleTicket st = new SaleTicket();
                // 售票中心分配票数
                sc.setNum(st);
                // 创建线程
                Thread t1 = new Thread(st, "一号窗口");
                Thread t2 = new Thread(st, "二号窗口");
                Thread t3 = new Thread(st, "三号窗口");
                Thread t4 = new Thread(st, "四号窗口");
                Thread t5 = new Thread(st, "五号窗口");
                Thread t6 = new Thread(st, "六号窗口");
                // 启动线程
                t1.start();
                t5.start();
                t4.start();
                t2.start();
                t6.start();
                t3.start();

        }
}

// 创建SaleTicket类实现Runnable接口
class SaleTicket implements Runnable {
        private int tickets;

        public void setTotalNum(int tickets) {
                // 设置发售总票数
                this.tickets = tickets;
        }

        // 方法中实现加同步锁
        private synchronized void sale() {
                if (tickets > 0) {
                        System.out.println(Thread.currentThread().getName() + "售出第:   "
                                        + (tickets--) + "张票");
                        // 可能有异常抓获
                        try {
                                Thread.sleep(tickets);
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                }
        }

        // 接口的run()方法
        public void run() {
                while (tickets > 0) {
                        sale();
                }
        }
}

// 创建SaleCenter类
class SaleCenter {
        private int ticketsnum;

        SaleCenter(int ticketsnum) {
                this.ticketsnum = ticketsnum;
        }

        public void setNum(SaleTicket st) {
                st.setTotalNum(ticketsnum); // 授权票数上限
        }
}
好几个窗口同时卖票,
回复 使用道具 举报
本帖最后由 翁发达 于 2012-9-8 09:31 编辑

上面几位朋友不知是没有看清我的题目还是怎么的,答案不是我想要的,我的需求已用红色字体标出来了,有两个:1,必须在方法内,和方法上,都实现加锁,
2,必须两个线程都有执行,我看把几位的代码放进去运行,要么只有一个synchronized,要么一直都是只有一个线程运行,直到结束.
而不仅仅把票卖了,希望朋友们再看下....
回复 使用道具 举报
这个问题谁能帮我搞定下?我要多个线程一起跑,而不是单个,如果是单个跑完全程,我源代码就实现了
回复 使用道具 举报
class Sou implements Runnable {
        static boolean falg = true;
        private static int a = 100; //实例变量
        int count = 1;// 定义一个记数器,看最终是不是100张票.

        public synchronized void sell() {
                int a = 200;//局部变量
                while (a > 0) {
                        if (a > 0) {
                                System.out.println(Thread.currentThread().getName() + ":  " + a
                                                + "sell--top---" + count++);
                                try {
                                        Thread.sleep(10);
                                } catch (Exception e) {
                                }
                                a--;
//                                System.out.println(Thread.currentThread().getName() + ":  " + a
//                                                + "sell---end--" + count++);
                        }
                }
        }

        public void run() {
                int a = 150;//局部变量
                if (falg) {
                        while (a > 0) {
                                synchronized (Sou.class) { //锁标记 this
                                        if (a > 0) {
                                                System.out.println(Thread.currentThread().getName()
                                                                + ":  " + a + "run-----" + count++);
                                                try {
                                                        Thread.sleep(10);
                                                } catch (Exception e) {
                                                }
                                                a--;
                                        }

                                }
                        }
                } else {
                        sell();
                }
        }
}

Runnable r =new Sou();
                  Thread  t =new Thread(r);
                  Thread  t1 =new Thread(r);
                  t.start();
                  try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
                  Sou.falg=false;
                  t1.start();
原因:你在主函数中没有“切换”,就是所指的sleep,调用你的sell(),而你的代码里写的这个主要是因为你的单个线程中实现刷新,而主函数中对于两个线程实现切换。
程序的健壮性:你的实例变量加static表示常量,预编译的时候已经在内存中初始值。
回复 使用道具 举报
class Sou implements Runnable {
        static boolean falg = true;
        private static int a = 100; //实例变量
        int count = 1;// 定义一个记数器,看最终是不是100张票.

        public synchronized void sell() {
                int a = 200;//局部变量
                while (a > 0) {
                        if (a > 0) {
                                System.out.println(Thread.currentThread().getName() + ":  " + a
                                                + "sell--top---" + count++);
                                try {
                                        Thread.sleep(10);
                                } catch (Exception e) {
                                }
                                a--;
//                                System.out.println(Thread.currentThread().getName() + ":  " + a
//                                                + "sell---end--" + count++);
                        }
                }
        }

        public void run() {
                //int a = 150;//局部变量
                if (falg) {
                        while (a > 0) {
                                synchronized (Sou.class) { //锁标记 this
                                        if (a > 0) {
                                                System.out.println(Thread.currentThread().getName()
                                                                + ":  " + a + "run-----" + count++);
                                                try {
                                                        Thread.sleep(10);
                                                } catch (Exception e) {
                                                }
                                                a--;
                                        }

                                }
                        }
                } else {
                        sell();
                }
        }
}

Runnable r =new Sou();
                  Thread  t =new Thread(r);
                  Thread  t1 =new Thread(r);
                  t.start();
                  try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
                  Sou.falg=false;
                  t1.start();
原因:你在主函数中没有“切换”,就是所指的sleep,调用你的sell(),而你的代码里写的这个主要是因为你的单个线程中实现刷新,而主函数中对于两个线程实现切换。
程序的健壮性:你的实例变量加static表示常量,预编译的时候已经在内存中初始值。
   注意:局部变量要先赋值,再进行运算,而实例变量均已经赋初值。这是局部变量和实例变量的一大区别。(我程序里面给你加了局部变量,你可以看下效果)这个也是小知识点。
回复 使用道具 举报
class Sou implements Runnable {
        static boolean falg = true;
        private static int a = 100; //实例变量
        int count = 1;// 定义一个记数器,看最终是不是100张票.

        public synchronized void sell() {
                int a = 200;//局部变量
                while (a > 0) {
                        if (a > 0) {
                                System.out.println(Thread.currentThread().getName() + ":  " + a
                                                + "sell--top---" + count++);
                                try {
                                        Thread.sleep(10);
                                } catch (Exception e) {
                                }
                                a--;
//                                System.out.println(Thread.currentThread().getName() + ":  " + a
//                                                + "sell---end--" + count++);
                        }
                }
        }

        public void run() {
                //int a = 150;//局部变量
                if (falg) {
                        while (a > 0) {
                                synchronized (Sou.class) { //锁标记 this
                                        if (a > 0) {
                                                System.out.println(Thread.currentThread().getName()
                                                                + ":  " + a + "run-----" + count++);
                                                try {
                                                        Thread.sleep(10);
                                                } catch (Exception e) {
                                                }
                                                a--;
                                        }

                                }
                        }
                } else {
                        sell();
                }
        }
}

Runnable r =new Sou();
                  Thread  t =new Thread(r);
                  Thread  t1 =new Thread(r);
                  t.start();
                  try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
                  Sou.falg=false;
                  t1.start();
原因:你在主函数中没有“切换”,就是所指的sleep,调用你的sell(),而你的代码里写的这个主要是因为你的单个线程中实现刷新,而主函数中对于两个线程实现切换。
程序的健壮性:你的实例变量加static表示常量,预编译的时候已经在内存中初始值。
   注意:局部变量要先赋值,再进行运算,而实例变量均已经赋初值。这是局部变量和实例变量的一大区别。(我程序里面给你加了局部变量,你可以看下效果)这个也是小知识点。
回复 使用道具 举报
class Sou implements Runnable {
        static boolean falg = true;
        private static int a = 100; //实例变量
        int count = 1;// 定义一个记数器,看最终是不是100张票.

        public synchronized void sell() {
                int a = 200;//局部变量
                while (a > 0) {
                        if (a > 0) {
                                System.out.println(Thread.currentThread().getName() + ":  " + a
                                                + "sell--top---" + count++);
                                try {
                                        Thread.sleep(10);
                                } catch (Exception e) {
                                }
                                a--;
//                                System.out.println(Thread.currentThread().getName() + ":  " + a
//                                                + "sell---end--" + count++);
                        }
                }
        }

        public void run() {
                //int a = 150;//局部变量
                if (falg) {
                        while (a > 0) {
                                synchronized (Sou.class) { //锁标记 this
                                        if (a > 0) {
                                                System.out.println(Thread.currentThread().getName()
                                                                + ":  " + a + "run-----" + count++);
                                                try {
                                                        Thread.sleep(10);
                                                } catch (Exception e) {
                                                }
                                                a--;
                                        }

                                }
                        }
                } else {
                        sell();
                }
        }
}

Runnable r =new Sou();
                  Thread  t =new Thread(r);
                  Thread  t1 =new Thread(r);
                  t.start();
                  try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
                  Sou.falg=false;
                  t1.start();
原因:你在主函数中没有“切换”,就是所指的sleep,调用你的sell(),而你的代码里写的这个主要是因为你的单个线程中实现刷新,而主函数中对于两个线程实现切换。
程序的健壮性:你的实例变量加static表示常量,预编译的时候已经在内存中初始值。
   注意:局部变量要先赋值,再进行运算,而实例变量均已经赋初值。这是局部变量和实例变量的一大区别。(程序里面给你加了局部变量,你可以看下效果)这个也是小知识点。
回复 使用道具 举报
class Sou implements Runnable {
        static boolean falg = true;
        private static int a = 100; //实例变量
        int count = 1;// 定义一个记数器,看最终是不是100张票.

        public synchronized void sell() {
                int a = 200;//局部变量
                while (a > 0) {
                        if (a > 0) {
                                System.out.println(Thread.currentThread().getName() + ":  " + a
                                                + "sell--top---" + count++);
                                try {
                                        Thread.sleep(10);
                                } catch (Exception e) {
                                }
                                a--;
//                                System.out.println(Thread.currentThread().getName() + ":  " + a
//                                                + "sell---end--" + count++);
                        }
                }
        }

        public void run() {
                //int a = 150;//局部变量
                if (falg) {
                        while (a > 0) {
                                synchronized (Sou.class) { //锁标记 this
                                        if (a > 0) {
                                                System.out.println(Thread.currentThread().getName()
                                                                + ":  " + a + "run-----" + count++);
                                                try {
                                                        Thread.sleep(10);
                                                } catch (Exception e) {
                                                }
                                                a--;
                                        }

                                }
                        }
                } else {
                        sell();
                }
        }
}

Runnable r =new Sou();
                  Thread  t =new Thread(r);
                  Thread  t1 =new Thread(r);
                  t.start();
                  try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
                  Sou.falg=false;
                  t1.start();
原因:你在主函数中没有“切换”,就是所指的sleep,调用你的sell(),而你的代码里写的这个主要是因为你的单个线程中实现刷新,而主函数中对于两个线程实现切换。
程序的健壮性:你的实例变量加static表示常量,预编译的时候已经在内存中初始值。
   注意:局部变量要先赋值,再进行运算,而实例变量均已经赋初值。这是局部变量和实例变量的一大区别。(程序里面给你加了局部变量,你可以看下效果)这个也是小知识点。
回复 使用道具 举报
class Sou implements Runnable {
        static boolean falg = true;
        private static int a = 100; //实例变量
        int count = 1;// 定义一个记数器,看最终是不是100张票.

        public synchronized void sell() {
                int a = 200;//局部变量
                while (a > 0) {
                        if (a > 0) {
                                System.out.println(Thread.currentThread().getName() + ":  " + a
                                                + "sell--top---" + count++);
                                try {
                                        Thread.sleep(10);
                                } catch (Exception e) {
                                }
                                a--;
//                                System.out.println(Thread.currentThread().getName() + ":  " + a
//                                                + "sell---end--" + count++);
                        }
                }
        }

        public void run() {
                //int a = 150;//局部变量
                if (falg) {
                        while (a > 0) {
                                synchronized (Sou.class) { //锁标记 this
                                        if (a > 0) {
                                                System.out.println(Thread.currentThread().getName()
                                                                + ":  " + a + "run-----" + count++);
                                                try {
                                                        Thread.sleep(10);
                                                } catch (Exception e) {
                                                }
                                                a--;
                                        }

                                }
                        }
                } else {
                        sell();
                }
        }
}

Runnable r =new Sou();
                  Thread  t =new Thread(r);
                  Thread  t1 =new Thread(r);
                  t.start();
                  try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
                  Sou.falg=false;
                  t1.start();
原因:你在主函数中没有“切换”,就是所指的sleep,调用你的sell(),而你的代码里写的这个主要是因为你的单个线程中实现刷新,而主函数中对于两个线程实现切换。
程序的健壮性:你的实例变量加static表示常量,预编译的时候已经在内存中初始值。
   注意:局部变量要先赋值,再进行运算,而实例变量均已经赋初值。这是局部变量和实例变量的一大区别。(程序里面给你加了局部变量,你可以看下效果)这个也是小知识点。
回复 使用道具 举报
我的天,系统刚才卡了,发了这么多
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马