[译]SEI CERT Oracle Coding Standard for Java - Thread Apis(THI00-J)

原文:https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=88487735

THI00-J. Do not invoke Thread.run()

使用该方法启动线程具有迷惑性,看起来是启动新的线程执行方法,但实际上,执行方法的线程是不对的。 调用Thread.start()才能启动新的线程执行线程的run()方法,直接调用Thread对象的run()方法并不能达到目的。事实上,调用Thread对象的run()方法是当前线程执行了run()方法中的语句,而非新启动的线程。更糟糕的是,如果这个Thread对象是通过Thread类的子类实例化的,并且这个子类并没有覆盖父类的run()方法,那么调用它的run()方法什么都不会执行。总而言之,代码中一定不要直接调用Thread对象的run()方法。

不规范的代码

下面的代码从当前线程执行了run()方法:

public final class Foo implements Runnable {
  @Override public void run() {
    // ...
  }
 
  public static void main(String[] args) {
    Foo foo = new Foo();
    new Thread(foo).run();
  }
}

这里new出来的线程根本不会启动,我们想当然的认为调用run()方法就启动的新线程,但结果是,当前线程执行了run()方法中的语句。

规范的代码

下面的代码通知Java运行时启动一个新的线程执行run()方法:

public final class Foo implements Runnable {
  @Override public void run() {
    // ...
  }
 
  public static void main(String[] args) {
    Foo foo = new Foo();
    new Thread(foo).start();
  }
}

例外

THI00-J-EX0
在进行单元测试时,我们可能会直接调用Thread对象的run()方法,测试run()方法中的逻辑,但是需要注意,不要以这种方式在多线程环境下测试。

public void sampleRunTest() {
 
  Thread thread = new Thread(new Runnable() {
      @Override public void run() {
        // ...
      }
    });
   
  ((Runnable) thread).run();  // THI00-J-EX0: Does not start a new thread
 
}

在调用run()方法前,将线程对象强制转换成Runnable对象,明确告知是有意的调用run()方法进行测试,同时强烈建议给这行代码加一个明确的注释。
THI00-J-EX1
用于创建新线程的运行时系统代码是允许直接调用Thread对象的run()方法的,对于Java运行时系统,这样直接调用显然是必要的,然而需要注意,上层用户代码需要采用这种调用方式的场景是几乎没有的。

如果觉得我的文章对您有用,请在支付宝公益平台找个项目捐点钱。 @sxzhou Oct 26, 2017

奉献爱心