views:

589

answers:

4

I've encountered a very strange problem. My program looks like this:

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
  }

The problem is the Inner class seems never run really. So the func will always stop it before it does what it supposed to do. The two threads should run concurrently, but actually only the main thread is running, the other is in running state, but blocked. I try to change the Inner class to be a static class. This time it works well. But still I don't the reason, hope someone can help to explain it.

+4  A: 

Your problem can not be reproduced.

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();
    }

}

This actually runs perfectly and outputs both “outer” and “inner”.

Bombe
A: 

My initial thought is that you're seeing a thread scheduling "accident". You're not showing us your real code, so it's hard to see if that's possible. I woudl have expected a sleep() where you show the comment to prevent that, but we can't see the real code.,

However, another thought, you say

the func will always stop it before it does what it supposed to do

That's seems odd. I would expect to use some kind of shared state variable, with synchs and waits to ensure that the two threads agree on what's happening. Using those you tend to inevitably yield control so that the two threads get a time slice.

As an experiment I might add a Thread.yield() call after the start to see if that has any effect.

djna
My intention to prevent the working thread runs too long, so I sleep for a while to set time limitation, after that the program keeps going
gleery
A: 
       // Thread.sleep() for a while to see if the above thread has finished
       // if not stop the thread

My guess is that there's some issue with this logic, and you're stopping the thread when you shouldn't. Of course without an example that reproduces the problem it's impossible to tell.

patros
In eclipse debugger, it shows that the thread is in running state
gleery
A: 

I've just tried to write a simple code to show the problem, but I failed. It seems this problem is not about static and non-staic class, since non-static class also works fine if I don't use a member variable in the outter class. But once i use it, the problem happens. Reproducing the problem is not so easy. The following code works with no problem.

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();
    }

}
gleery
When you’re accessing members of the outer class you need to make sure that you’re synchronizing access to it properly; this might in fact be the problem you’re really facing.
Bombe
What Bombe said. Try declaring the member variable `volatile` and seeing if the problem goes away. (I wouldn't recommend `volatile` as an actual fix, though, just a way to tell if thread-visibility of data is the issue.)
David Moles