关于多个胎面上的相同Runnable参考

Ull*_*las 1 java multithreading

当我们start()通过传递一个Runnable对象作为参数调用一个Thread时,我们可以传递相同的Runnable引用来启动多个线程吗?

public class MyMain {
    public static void main(String[] args) {
        MyRunnableImpl impl = new MyRunnableImpl();
        new Thread(impl).start();
        new Thread(impl).start();
    }
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*eid 7

是的,您可以在Runnable相应实施时执行此操作.

但是你必须要小心你的Runnable实现不包含可变状态.您可以在自己的实现中控制它,但Runnable合同没有指定.

// can be used for multiple Threads
class StatelessRunnable {
  public void run() {
    doSomething();
  }
}

// may go bang on the second execution -> use two instances
class StatefulRunnable {
  volatile boolean canRun = true;
  public void run() {
    if(!canRun) throw new IllegalStateException();
    canRun = false;
  }
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,您可以看到可以使用任意StatelessRunnable数量的线程.事实上你甚至可以把它变成一个单身人士.StatefulRunnable相比之下,每个实例只能运行一次.

共享国家

阅读Jon的回答我意识到可能存在您实际想要共享两个Runnable实例状态的情况.当然,有状态Runnable实例并不总是会因多线程而失败,但这比无状态实例要复杂得多.

// willingly share state over threads
class WillinglyStatefulRunnable {
  final BlockingQueue<Object> sharedObjects = new BlockingQueue<Object>();
  public void run() {
    sharedObjects.offer(new Object());
  }
}
Run Code Online (Sandbox Code Playgroud)

上面的示例显示了如何sharedObjects使用多个线程处理单个集合.

文学旁注:

Joshau Bloch的Effective Java中的第15项称最小化可变性.本章 - 如果您有权访问该书 - 在更广泛的背景下解决类似的问题.简而言之,他指出,不可变对象使得重用实例和减少非法状态的可能性变得更加容易.