了解在java中实现Runnable的线程

时间:2014-07-03 06:29:51

标签: java multithreading runnable

我正在尝试理解Java中的Threads。我创建了一个实现Runnable接口的线程,该接口执行某个类的某个功能。以下是Java类:

MyThread Class

public class MyThread implements Runnable {
    private DataContainer dataContainer;
    private Thread thread;
    public MyThread(DataContainer dataContainer) {
        this.dataContainer = dataContainer;
        thread = new Thread(this);
        thread.start();
        thread.setName("Thread 2");
    }
    @Override
    public void run() {
        System.out.println("MyThread : "+dataContainer.toString());
    }
    public void runThread() {
        thread.run();
    }
}

DataContainer Class。我在线程中执行的功能

public class DataContainer {
    private static DataContainer instance = null;
    private DataContainer() {}
    public static DataContainer getInstance() {
        if(null == instance)
            instance = new DataContainer();
        return instance;
    }
    @Override
    public String toString() {
        return Thread.currentThread().getName()+" : __Data__";
    }
}

main class

public class Launcher {
    public static void main(String[] args) {
        DataContainer dataContainer = DataContainer.getInstance();
        MyThread myThread = new MyThread(dataContainer);

        int i =0;
        while(i++<10) {
            System.out.println("Launcher : "+ dataContainer.toString());
            myThread.runThread();
        }
    }
}

问题是,在while循环中,从主类和myThread实例执行dataContainer.toString(),我得到输出,因为它们都在一个线程中运行:{{1} }。循环中的所有执行都不是从main thread执行的。

我的目标是,Thread 2在线程in the while loop, I want myThread.runThread()下执行。

修改

添加了Thread 2。 但是,现在只执行一次?每次我想执行myThread.runThread()时都无法创建新线程。通过在循环中创建一个新线程,我最终会创建一堆线程。这是可取的吗?我想要一个代码(比如Y)由一个线程(比如说X)执行。每次Y必须执行时,都应该通过线程X来完成。

解决方案

这可能是一个可能的解决方案:

thread.start()

4 个答案:

答案 0 :(得分:3)

thread.run();只是在当前线程的上下文中直接调用Runnable s run方法。如果您只是在run()方法中调用runThread,则会得到相同的结果。

您需要致电thread.start(),这将创建一个新的流程线程并最终调用您的Runnable run方法

您应该创建Thread并在需要时将Runnable设置为Thread,而不是将Runnable换成public class MyThread implements Runnable { private DataContainer dataContainer; public MyThread(DataContainer dataContainer) { this.dataContainer = dataContainer; } @Override public void run() { System.out.println("MyThread : "+dataContainer.toString()); } } ,这是违反直觉且通常设计不合理的问题。 ,例如......

DataContainer dataContainer = DataContainer.getInstance();
MyThread myThread = new MyThread(dataContainer);

Thread thread = new Thread(myThread );
thread.setName("Thread 2");
thread.start();

System.out.println("Launcher : " + dataContainer.toString());

然后你可以做一些像......

{{1}}

答案 1 :(得分:1)

myThread.runThread()将在当前线程中调用该方法。如果您希望在新线程中执行该操作,请将该调用置于run方法中,然后只需调用myThread.start()。这将启动另一个线程,并调用runnable对象的run方法。

答案 2 :(得分:1)

定义实现Runnable的类时,不需要包含Thread对象。

简单地

 class myThread implements Runnable {

     @Override
    public void run() {
          // do something
   }
}


new Thread (new myThread ()).start ();

答案 3 :(得分:0)

我没有尝试理解你的例子(过于复杂),但这是个坏主意:

public class Foobar implements Runnable {
    private XType x;
    private YType y;
    private Thread thread;

    public Foobar() {
        x = new XType();
        thread = new Thread(this);   //Not in a constructor!!!
        thread.start();
        y = new YType();
    }

    @Override
    public void run() {
        doSomethingWith(y);       // y can be uninitialized at this point.
        doSomethingElseWith(x);   // x can be uninitialized too!!!
    }
}

这个反模式有一个名称,它被称为&#34;从构造函数中泄漏this。&#34; Foobar构造函数启动新线程,并在新对象完全初始化之前为其提供对新Foobar实例(即this)的引用。当以这种方式发布对象时,Java语言规范不保证对象对新线程的外观。 (Google for&#34; safe publication&#34;)

特别是,当首次输入run()方法时,任何对象的成员变量(包括x !!)都可能从新线程的角度看似未初始化。 / p>

最佳实践:不要在构造函数或构造函数调用的任何帮助方法中使用this,并且还要将帮助器声明为final,以便class不能覆盖一个并以这种方式查看未初始化的对象。

class Foobar {

    Foobar(...) {
        ...don't use "this" here...
        fooHelper(...);
    }

    private final void fooHelper(...) {
        ...don't use "this" here either...
    }
}