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

时间:2012-03-05 06:29:07

标签: java concurrency

使用相同的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());
        }
    }
}

4 个答案:

答案 0 :(得分:18)

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

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

答案 1 :(得分:9)

由于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();
    }        
}

什么得到printed?当您确实需要在线程之间共享状态时,最好使用java.util.concurrent中的类。它们主要由多线程专家(Doug LeaConcurrent Programming in Java的作者)编写,并经过许多人的测试。为自己省一些心痛。 :)

答案 2 :(得分:7)

  

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

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

  

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

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


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

答案 3 :(得分:0)

为了便于理解(基于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();
}
}