1

When we call start() on a Thread by passing a Runnable object as argument, can we pass the same Runnable reference to start multiple threads?

public class MyMain {
    public static void main(String[] args) {
        MyRunnableImpl impl = new MyRunnableImpl();
        new Thread(impl).start();
        new Thread(impl).start();
    }
}
4

1 回答 1

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

在上面的示例中,您可以看到可以使用任意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());
  }
}

上面的示例显示了如何处理sharedObjects具有多个线程的单个集合。

文学旁注

Joshau Bloch 的 Effective Java中的第 15 项说Minimize Mutabilty。本章——如果你能接触到这本书——在更一般的背景下解决了类似的问题。他简短地总结说,不可变对象可以更容易地重用实例并减少非法状态的可能性。

于 2013-05-18T13:29:30.380 回答