为什么不在构造函数中启动线程?如何终止?

2022-08-31 21:02:53

我正在学习如何在Java中使用线程。我写了一个类,它实现Runnable并发运行到另一个线程。主线程处理侦听串行端口,而第二个线程将处理将数据发送到同一端口。

public class MyNewThread implements Runnable {
    Thread t;

    MyNewThread() {
        t = new Thread (this, "Data Thread");
        t.start();
    }

    public void run()  {
        // New Thread code here 
    }

第一个线程像这样启动第二个线程:

public class Main {
    public static void main(String[] args) throws Exception{
        new MyNewThread();
        // First thread code there
    }  
}

这有效,但我的编译器标记了一个警告,说:在构造函数中启动新线程是危险的。这是为什么呢?

这个问题的第二部分是:如果我在一个线程(串行端口监听线程)中运行一个循环,并且我在第二个线程中键入exit命令,该怎么办。如何终止第一个线程?谢谢。


答案 1

对于您的第一个问题:在传入转义的构造函数中启动线程。这意味着在完全构造对象之前,您实际上会给出对对象的引用。线程将在构造函数完成之前启动。这可能会导致各种奇怪的行为。thisthis

对于你的第二个问题:在Java中没有可接受的方法强制另一个线程停止,所以你将使用一个变量,线程会检查该变量以了解它是否应该停止。另一个线程将设置它以指示第一个线程将停止。变量必须是可变的,或者所有访问都必须同步,以确保正确发布。这里有一些代码,就像你想要的一样。

public class MyNewThread implements Runnable {

    private final Thread t;
    private volatile boolean shouldStop = false;

    MyNewThread() {
        t = new Thread (this, "Data Thread");
    }

    public void start() {
        t.start();
    }

    public void stop() {   
         shouldStop = true;
    }

    public void run()  {
         while(!shouldStop)
         {
             // do stuff
         }
    }
}

无论想要创建和启动线程的任何内容都可以:

MyNewThread thread = new MyNewThread();
thread.start();

任何想要停止线程的东西都可以:

thread.stop();

答案 2

让我们看一个基本示例:

class MyClass implements Runnable{
   int a = 0;
   String b = null;

   public MyClass(){
       new Thread(this).start();
       b = "Foo";
   }

   public void run(){
      a = b.length(); //can throw NullPointerException
   }
}

在这个例子中,MyClass.this据说是逃避构造函数的。这意味着该对象可供引用,但可能无法创建在构造函数中构建的所有字段。要将其提升到另一个级别,如果b是,您会期望它可用,但不能保证。这被称为部分构造的对象,在java中是完全合法的。final