使用runnable的相同实例初始化两个线程

使用相同的runnable实例初始化两个线程是不是很糟糕的编程? 使用runnable的单独实例进行初始化会有什么不同,并且对于runnable的同一实例共享内存位置与性能有什么关系?

public static void main(String[] args)throws Exception { H h = new H(); H h2 = new H(); Thread j = new Thread(h); j.setName("11"); Thread jj = new Thread(h);//instead of new H() jj.setName("22"); j.start(); jj.start(); } class H implements Runnable { public void run() { while(true) { System.out.println(Thread.currentThread().getName()); } } } 

只要您运行的代码旨在支持它,就可以完成它。 它不仅可以通过单个实例而不是多个实例来节省一些内存,但如果这些线程试图通过共享数据进行通信,那么它可能是绝对必需的!

不可否认,通过共享状态进行通信是线程经常变得棘手的地方,因此需要仔细完成,但从线程系统本身的角度来看,让两个线程调用单个Runnable实例的run方法绝对没有问题。

由于H没有任何实例状态,因此使用多个实例无关紧要。 Runnable实例开始存储状态时需要注意。

 public class Main implements Runnable { volatile int i; public void run() { for (i = 0; i < 100; i++) { System.out.println(i); } } public static void main(String[] args) { Main a = new Main(); Thread t1 = new Thread(a); Thread t2 = new Thread(a); t1.start(); t2.start(); } } 

打印什么? 当你需要在线程之间共享状态时,最好使用java.util.concurrent的类。 它们主要由multithreading专家( Doug Lea , Java并行编程的作者) 编写,并经过许多人的测试。 为自己省一些心痛。 🙂

使用相同的runnable实例初始化两个线程是不是很糟糕的编程?

不是特别的。 但是,如果Runnable实例具有实例字段,那么您需要确保线程对字段的所有访问都已正确同步,这将使代码更复杂。

使用runnable的单独实例进行初始化会有什么不同,并且对于runnable的同一实例共享内存位置与性能有什么关系?

通过在多个线程之间共享Runnable实例而节省的内存是无关紧要的……除非Runnable拥有大量的实例数据。 (如果确实如此,则可能会使实例无法共享。)


您的H类是一个示例,其中共享实例是安全的,但没有意义,因为内存节省是无关紧要的。 (没有实例字段的Runnable对象大约占用8到16个字节,具体取决于平台。)

为了便于理解(基于Stephen的注释),添加了以下程序块,关于从非同步块访问实例变量的影响与Runnable的相同实例显示意外结果。

 public class SynchronizedInstanceMethod implements Runnable{ private int counter; public SynchronizedInstanceMethod(int counterValue){ this.counter = counterValue; } private synchronized void displayMessage(){ System.out.println(" Display Message "); } private void modifyCounter(){ this.counter++; System.out.println("Value -- "+ this.counter); } @Override public void run() { this.displayMessage(); this.modifyCounter(); } public static void main(String[] args) { SynchronizedInstanceMethod instance = new SynchronizedInstanceMethod(5); new Thread(instance).start(); new Thread(instance).start(); } }