简体   繁体   English

了解在Java中实现Runnable的线程

[英]Understanding Threads implementing Runnable in java

I'm trying to understand Threads in Java. 我试图了解Java中的线程。 I've created a thread implementing the Runnable interface, which executes a certain function of a certain class. 我创建了一个实现Runnable接口的线程,该接口执行某个类的某个功能。 The following are the Java classes: 以下是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();
    }
}

The DataContainer Class . DataContainer Class The function of which I execute in the thread 我在线程中执行的功能

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__";
    }
}

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

The problem is, in the while loop where is execute the dataContainer.toString() from the main class and the myThread instance, I get the output as they are all running in one thread: main thread . 问题是,在while循环中,从主类和myThread实例执行dataContainer.toString()时,我得到了输出,因为它们都在一个线程中运行: main thread None of the executions in the loop are executed from Thread 2 . 循环中的所有执行都不是从Thread 2执行的。

My aim is that, in the while loop, I want myThread.runThread() to be executed under the thread Thread 2 . 我的目标是, in the while loop, I want myThread.runThread()在线程Thread 2下执行。

EDIT: 编辑:

Added thread.start() . 添加了thread.start() However, now it gets executed only once? 但是,现在只执行一次? I can't create a new thread every time I want to execute myThread.runThread(). 我每次想执行myThread.runThread()时都无法创建新线程。 By creating a new thread in the loop, I'd end up creating a bunch of threads. 通过在循环中创建一个新线程,我最终将创建一堆线程。 Is this advisable? 这是明智的吗? I want a certain piece of code(say Y) to be executed by a thread(say X). 我希望某个线程(例如X)执行某段代码(例如Y)。 Every time Y has to be executed, it should be done through the thread X. 每次必须执行Y时,都应该通过线程X完成。

Solution

This can be a possible solution: 这可能是一种解决方案:

public class MyThread implements Runnable {
    private DataContainer dataContainer;
    private Thread thread = null;
    public MyThread(DataContainer dataContainer) {
        this.dataContainer = dataContainer;
    }
    @Override
    public void run() {
        System.out.println("MyThread : "+dataContainer.toString());
    }
    public void runThread() {
        boolean threadIsAlive = (null!=thread && Thread.getAllStackTraces().keySet().contains(thread));
        if(null == thread || !threadIsAlive) {
            thread = new Thread(this);
            thread.start();
        } else {
            thread.run();
        }
    }
}

thread.run(); is just calling your Runnable s run method directly, within the current thread's context. 只是在当前线程的上下文中直接调用您的Runnablerun方法。 You'll get the same result if you're simply called run() in you runThread method. 如果在runThread方法中简单地调用run()runThread获得相同的结果。

You need to call thread.start() , this will create a new process thread and eventually call your Runnable s run method 您需要调用thread.start() ,这将创建一个新的进程线程,并最终调用您的Runnablerun方法

Rather than wrapping a Thread instead a Runnable , which is counterintuitive and generally bad design, you should create Thread and set the Runnable to it when you need to, for example... 而不是包装一个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());
    }
}

Then you could do something like... 然后您可以做类似...

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

myThread.runThread() will just invoke that method in current thread. myThread.runThread()只会在当前线程中调用该方法。 If you want that to be executed in new thread, put that call in run method and just call myThread.start() . 如果希望在新线程中执行该调用,请将该调用放入run方法,然后调用myThread.start() This starts another thread and calls run method of your runnable object. 这将启动另一个线程并调用可运行对象的run方法。

When you define a class which implements Runnable, you do not need to have a Thread object in it. 在定义实现Runnable的类时,不需要在其中具有Thread对象。

Simplistically 简单地

 class myThread implements Runnable {

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


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

I didn't try to understand your example (too convoluted), but this is a bad idea: 我没有试图理解您的示例(太费解了),但这是一个坏主意:

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!!!
    }
}

This anti-pattern has a name, It's called "leaking this from a constructor." 这种反模式都有一个名字,这就是所谓的“跑冒滴漏this从一个构造函数。” The Foobar constructor starts the new thread, and gives it a reference to the new Foobar instance (ie, this ) before the new object has been fully initialized. Foobar构造函数启动新线程,并在完全初始化新对象之前为其提供对新Foobar实例(即this )的引用。 The Java language spec makes no guarantees about what the object will look like to the new thread when the object is published in this manner. Java语言规范不保证当以这种方式发布对象时,该对象在新线程中的外观如何。 (Google for "safe publication") (Google用于“安全发布”)

In particular, When the run() method is first entered, any of the object's member variables (including x!!) can appear to be uninitialized from the new thread's point of view. 特别是,当首次输入run()方法时,从新线程的角度看,该对象的任何成员变量(包括x !!)似乎都未初始化。

Best Practice: Don't ever use this in a constructor or in any helper method that is called by the constructor, and also, declare helpers to be final so that a sub-class can't override one and see the un-initialized object that way. 最佳实践:永远不要在构造函数中或构造函数调用的任何辅助方法中使用this方法,也不要将辅助函数声明为final以便子类无法覆盖一个子类并查看未初始化的对象那样。

class Foobar {

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM