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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

  1. package cn.itcast.day1;

  2. public class EnumTest {
  3.            public static void main(String[] args){

  4.                   new Thread(new Runnable(){
  5.                          public void run(){
  6.                                   display(TrafficLamp.RED);
  7.                          }
  8.                   }).start();
  9.                   new Thread(new Runnable(){
  10.                          public void run(){
  11.                                   display(TrafficLamp.GREEN);
  12.                          }
  13.                   }).start();


  14.            }

  15.            public enum TrafficLamp{
  16.            //当抽象方法存在,必须覆盖枚举类中的抽象方法
  17.                      RED(25){
  18.                            public TrafficLamp nextLamp(){
  19.                                  return GREEN;
  20.                            }
  21.                      },GREEN(20){
  22.                            public TrafficLamp nextLamp(){
  23.                                  return YELLOW;
  24.                            }
  25.                     },YELLOW(5){
  26.                            public TrafficLamp nextLamp(){
  27.                                  return RED;
  28.                            }
  29.                     };

  30.                     public abstract TrafficLamp nextLamp();

  31.                     private int time;
  32.                     private TrafficLamp(int time){
  33.                              this.time = time;
  34.                     }
  35.                     public int getTime(){
  36.                              return time;
  37.                     }
  38.                    public void setTime(int time){
  39.                              this.time = time;
  40.                    }
  41.            }

  42.            public static void display(TrafficLamp state){
  43.                      while (true) {
  44.                                   switch (state) {
  45.                                          case GREEN:
  46.                                                      if (state.getTime() != 0) {
  47.                                                            state.setTime(lampSleep(state, state.getTime()));
  48.                                                      } else {
  49.                                                            state = state.nextLamp();
  50.                                                      }
  51.                                         case RED:
  52.                                                     if (state.getTime() != 0) {
  53.                                                            state.setTime(lampSleep(state, state.getTime()));
  54.                                                    } else {
  55.                                                            state = state.nextLamp();
  56.                                                    }
  57.                                        case YELLOW:
  58.                                                    if (state.getTime() != 0) {
  59.                                                            state.setTime(lampSleep(state, state.getTime()));
  60.                                                    } else {
  61.                                                            state = state.nextLamp();
  62.                                                    }
  63.                                }
  64.                     }
  65.            }

  66.            public static int lampSleep(TrafficLamp state,int count){
  67.                     try {
  68.                              Thread.sleep(1000);
  69.                     } catch (InterruptedException e) {
  70.                              e.printStackTrace();
  71.                     }
  72.                    System.out.println(state.toString()+count);
  73.                    count--;
  74.                    return count;
  75.           }

  76. }
复制代码
有没有人可以用eclipse运行一下以上代码,代码的目标是:
运行一个模拟交通灯,进行倒计时,红-->黄-->绿-->红,每秒都会输出“灯状态+剩余秒数”。

我遇到的问题是:
当交通灯走完一个循环以后,似乎阻塞住不动了,但是主线程还在运行中,因为运行并没有终止,这是怎么回事呢?
为了验证是不是主线程问题,我还自己在main中加了两个线程来运行,貌似仍然会出现同样的问题,

求帮助,求解答

7 个回复

倒序浏览
本帖最后由 贾联国 于 2012-5-3 00:44 编辑

  • 我觉得楼主的代码适合写成单线程,因为有state.nextLamp();,直接单线程互相转换就行。我运行了单线程,很正常~!

    主函数直接用:
    public static void main(String[] args){
                  new Thread(new Runnable(){

                         public void run(){

                                  display(TrafficLamp.RED);

                         }

                  }).start();


楼主写的代码非常好哇~!

不用state.nextLamp();的话可以用3线程的相互唤醒,不过不如楼主的简单~
回复 使用道具 举报
贾联国 发表于 2012-5-3 00:41
  • 我觉得楼主的代码适合写成单线程,因为有state.nextLamp();,直接单线程互相转换就行。我运行了单线程 ...

  • 谢谢夸奖,本人新人一枚。

    嗯,其实用单线程的话就和用main直接执行应该是一样的。
    我用两个线程是假设模拟东西方向 和 南北方向的灯转换。严谨一些应该加个同步什么的。为了单纯演示我就偷懒了。

    我试了一下,其实按理来说是只要不手动停止程序的话,是会一直循环打印的。但是我尝试了一次还是不行。比如打印 red--->green-->yellow 然后就停止打印了,但是Main函数还是在运行的。
    所以,不知道是我eclipse的问题,还是其他。

    不过还是感谢帮忙,因为帖子没什么人回。
    估计黑马9期招满了以后,论坛的活跃性就稍微减弱了吧。
    回复 使用道具 举报
    云惟桉 发表于 2012-5-3 01:04
    谢谢夸奖,本人新人一枚。

    嗯,其实用单线程的话就和用main直接执行应该是一样的。

    南北走向也是可以的,我的eclipse也是同样问题,但是控制台就没有问题。
    回复 使用道具 举报
    lz你的nextLamp实现貌似不是红-黄-绿-红的顺序 把返回值改一下吧、
    另外就是switch/case的地方,每一段之后就要break,否则每次循环三个case都执行,相当于,循环一次,同一个灯的time减减三次(time大于0的时候),比如起步是红灯,第一次循环之后,红灯的time减了3,其他灯没变。
    还有就是,在切换下一个灯之后,把下一个灯的时间重置,三个灯都走完一次不动就是因为他们的时间都归零了。这样我用单线程走了一次看起来是正常的。你自己再看一下吧,很晚了 先睡了明天还要上班{:soso_e136:}
    回复 使用道具 举报
    刘少伟 发表于 2012-5-3 02:20
    lz你的nextLamp实现貌似不是红-黄-绿-红的顺序 把返回值改一下吧、
    另外就是switch/case的地方,每一段之后 ...

    十分感谢帮忙!但是灯的状态是没错的,绿灯之后才是黄灯,生活里的顺序。
    另外,我查阅了一下java核心技术,才发现我的错,原文是这样的:

    【警告】:switch语句有可能触发多个case分支。如果在case分支语句的末尾没有break语句,那么就会接着执行下一个case分支语句。这种情况相当危险,常常会引发错误。为此,我们在程序中从不使用switch语句。
                                                                             ——P70 《Java核心技术:卷1:基础知识》

    细节真的使人挫败啊,楼主真是有心人。正确的解决方法就像你所说的,应该是考虑两点:
    1.运行过程使用set方法修改了time的值,因此在状态转换时一定需要重置time;
    2.没有break语句,无论满不满足case判断,每一个case都会执行(可以使用system.out输出检验)

    希望我的错误能给看帖的人带来收获。
    正确代码如下:
    1. public static void display(TrafficLamp state){
    2.           while (true) {
    3.                    switch (state) {
    4.                    case GREEN:
    5.                            if (state.getTime() != 0) {
    6.                                  state.setTime(lampSleep(state, state.getTime()));

    7.                            } else {
    8.                                  state = state.nextLamp();
    9.                                  state.setTime(5);
    10.                            }
    11.                            break;
    12.                    case RED:
    13.                            if (state.getTime() != 0) {
    14.                                  state.setTime(lampSleep(state, state.getTime()));
    15.                            } else {
    16.                                  state = state.nextLamp();
    17.                                  state.setTime(20);
    18.                            }
    19.                            break;
    20.                    case YELLOW:
    21.                            if (state.getTime() != 0) {
    22.                                  state.setTime(lampSleep(state, state.getTime()));
    23.                            } else {
    24.                                  state = state.nextLamp();
    25.                                  state.setTime(25);
    26.                            }
    27.                            break;
    28.                   }
    29.          }
    30. }
    复制代码
    回复 使用道具 举报
    贾联国 发表于 2012-5-3 01:37
    南北走向也是可以的,我的eclipse也是同样问题,但是控制台就没有问题。
    ...

    经过有心人提点,终于找到错误了。
    你可以看我的回复,希望你也有收获,呵呵。
    回复 使用道具 举报
    收获很大!
    回复 使用道具 举报
    您需要登录后才可以回帖 登录 | 加入黑马