50

我正在学习如何在 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
    }  
}

这可行,但我的编译器标记了一条警告:在构造函数中启动新线程很危险。为什么是这样?

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

4

4 回答 4

50

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

对于您的第二个问题:没有可接受的方法来强制另一个线程在 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();
于 2011-04-11T15:05:57.730 回答
12

让我们看一个基本的例子:

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 是final 您会期望它可用,但不能保证。这被称为部分构造的对象,在 java 中是完全合法的。

于 2011-04-11T15:11:11.883 回答
0

关于第二个问题,您可以通过方法检查第二个线程是否已终止isAlive,如果是,则使用break关键字关闭第一个线程的循环,然后如果无事可做将被终止

public class MyNewThread implements Runnable {
Thread t;

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

public void run()  {

   reading code ................
    // New Thread code here 
}

public class Main {
public static void main(String[] args) throws Exception{
   MyNewThread thread = new MyNewThread();

while(true)
{
    listening code ...................

    if(!thread.t.isAlive())
      break;
 }

}  
}
于 2013-02-10T13:42:47.797 回答
-5

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

让它一直循环直到达到一个条件。例如:

public void run() {
    while ( !inputConsole.getCommand().equals("exit") ) {
        //Do Something
        Thread.sleep(1000); //put thread to sleep for 1 second
    }
}
于 2011-04-11T15:09:05.823 回答