java中的线程争用

时间:2011-09-08 13:42:11

标签: java multithreading concurrency

我想了解下面的程序。如果我调用new ReaderThread().start()它工作正常,但如果我调用new ReaderThread().run(),应用程序将进入无限循环。有什么区别?

public class Contention {

    private static boolean ready;
    private static int number;

    private static class ReaderThread extends Thread {
        public void run() {
                 while (!ready){
                System.out.println("ready ..."+ready);
                Thread.yield();}
            System.out.println(number);
           // }
        }
    }


    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new ReaderThread().run();
        number = 42;
        ready = true;

    }

}

6 个答案:

答案 0 :(得分:11)

当你在同一个帖子中调用run()时。它只是一个方法调用。

当您致电start()以触发另一个线程来呼叫run()

这是扩展Thread不是一个好主意的原因之一,而是实现了用线程包装的Runnable。这是许多潜在混淆的原因之一。


这是一个相关的预告片

static String name = "Peter Lawrey";
static String state = "Washington";

static String getName() {
  return name;
}

static String getState() {
  return state;
}

static class NamedThread extends Thread {
  @Override
  public void run() {
    System.out.println(getName()+" - "+getState());
  }
}

public static void main(String... args) throws InterruptedException {
  new NamedThread().start();
}

打印

Thread-0 - RUNNABLE

你能找出原因吗?

答案 1 :(得分:4)

run()只是一种无法启动新主题的方法 - 因此main()永远不会将ready设置为true

只有start()实际上会产生一个单独的执行线程 - 这就是你需要的。

请注意,即使这样,由于内存模型问题,您的代码也无法保证正常工作 - 您需要担心对共享数据所做更改的可见性。

答案 2 :(得分:2)

仔细阅读java中的线程(例如http://download.oracle.com/javase/tutorial/essential/concurrency/

当你调用方法run()时,你可以像调用任何其他方法一样调用它,它将在与调用方法相同的线程中工作。

答案 3 :(得分:2)

如果你使用new ReaderThread().start();,你实际上是在创建一个新的线程实例,它将在后台运行,并main()继续执行。

但是new ReaderThread().run();创建了这个类的实例并对run()方法进行了常规方法调用,因此main()必须等到run()完成执行并将控件返回给main(),在你的情况下是一个无限循环。

如果你想开始一个新的线程然后开始使用ReaderThread().start();这是启动一个线程的正确方法,没有替代方案。

答案 4 :(得分:1)

public class Contention {

    private static boolean ready;
    private static int number;

    private static class ReaderThread extends Thread {
        public void run() {
                 while (!ready){
                System.out.println("ready ..."+ready);
                Thread.yield();}
            System.out.println(number);
           // }
        }
    }




    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new ReaderThread().run();//control goes to run() method

//and it keeps running and next line of code where you set ready=true will not be executed
        number = 42;
        ready = true;

    }

}

<强>编辑:

因为线程不是一起运行(但是同时运行),但是OS决定运行哪一个并且它确保每个线程都基于TimeShared基础(或任何算法)获得自己的机会。所以可能在你的情况下other thread首先获得机会并且在main()线程有机会运行并设置ready = true.之前执行它但是如果你再次运行你的代码,另一个案例也是可能。设置ready = true;Thread不会进入While()循环。

答案 5 :(得分:1)

当你有new ReaderThread().run();它在同一个帖子中时,ready = true;从未到达。

但是当你调用new ReaderThread().start()时,它会启动一个新线程,主线程也会继续,并且会点击ready = true; - 这将使循环中创建的线程...