【问题标题】:Java Thread using static or non-static nested class使用静态或非静态嵌套类的 Java 线程
【发布时间】:2009-09-07 06:41:45
【问题描述】:

我遇到了一个非常奇怪的问题。 我的程序如下所示:

class Outter{

      class Inner extends Thread {
           public void run(){
               // do something
           }
      }

      public void func() {
           new Inner().start();
           // Thread.sleep() for a while to see if the above thread has finished
           // if not stop the thread
  }

问题是 Inner 类似乎从未真正运行过。所以 func 总是会在它做它应该做的事情之前停止它。两个线程应该并发运行,但实际上只有主线程在运行,另一个处于运行状态,但是被阻塞了。 我尝试将 Inner 类更改为静态类。这次效果很好。 但我还是不知道原因,希望有人能帮忙解释一下。

【问题讨论】:

  • 请给出一个简短但完整的程序来演示问题。
  • 投票结束。用户发布了一个使问题无效的答案。
  • SSCCE (sscce.org) 会很好。

标签: java static multithreading non-static


【解决方案1】:

您的问题无法重现。

public class Outer {

    class Inner extends Thread {
        public void run() {
            System.out.println("inner");
        }
    }

    public void func() {
        new Inner().start();
        System.out.println("outer");
    }

    public static void main(String... args) {
        new Outer().func();
    }

}

这实际上运行完美,并输出“outer”和“inner”。

【讨论】:

    【解决方案2】:

    我最初的想法是你看到了一个线程调度“意外”。您没有向我们展示您的真实代码,因此很难确定这是否可能。我希望 sleep() 在其中显示评论以防止这种情况发生,但我们看不到真正的代码。,

    但是,你说的是另一个想法

    函数总是在它做它应该做的事情之前停止它

    这似乎很奇怪。我希望使用某种共享状态变量,同步和等待以确保两个线程就正在发生的事情达成一致。使用那些你会不可避免地让出控制权的线程,以便两个线程获得一个时间片。

    作为一个实验,我可能会在开始后添加一个 Thread.yield() 调用,看看是否有任何效果。

    【讨论】:

    • 为了防止工作线程运行时间过长,所以我睡了一会儿设置时间限制,然后程序继续运行
    【解决方案3】:
           // Thread.sleep() for a while to see if the above thread has finished
           // if not stop the thread
    

    我的猜测是这个逻辑存在一些问题,你在不应该的时候停止了线程。当然,如果没有重现问题的示例,就无法判断。

    【讨论】:

    • 在eclipse调试器中显示线程处于运行状态
    【解决方案4】:

    我刚刚尝试编写一个简单的代码来显示问题,但我失败了。 似乎这个问题与静态和非静态类无关,因为如果我不在外部类中使用成员变量,非静态类也可以正常工作。但是一旦我使用它,问题就会发生。 重现问题并不容易。下面的代码没有问题。

    package test;
    
    public class Tester {
    
        private String message = "Hello";
    
        private class Inner extends Thread {
    
            public void run(){
                try {
                    System.out.println(message);
                } catch (Exception e) {
                    // TODO: handle exception
                }
    
            }
        }
    
        public void func(){
            Inner inner = new Inner();
            inner.start();
    
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO: handle exception
            }
            System.out.println("stop");
        }
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            new Tester().func();
        }
    
    }
    

    【讨论】:

    • 当您访问外部类的成员时,您需要确保正确同步访问它;这实际上可能是您真正面临的问题。
    • Bombe 说了什么。尝试声明成员变量volatile 并查看问题是否消失。 (不过,我不建议将 volatile 作为实际解决方案,这只是一种判断数据的线程可见性是否存在问题的方法。)
    猜你喜欢
    • 2015-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多