使用相同的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());
}
}
}
答案 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 Lea,Concurrent 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();
}
}