下面两个Java多线程代码之间有什么区别?

3
想知道下面两个代码之间的区别
我的第一个代码是:
package com.app.myclasses;

class RunnableTest implements Runnable {
    @Override
    public void run() {
        // TODO Auto-generated method stub

        for (int i = 0; i < 5; i++) {
            System.out.println(i);
        }
    }
}
public class ThreadTesting {
    public static void main(String[] args) {
        RunnableTest r1 = new RunnableTest();
        Thread t1 = new Thread(r1, "first");
        t1.start();
        Thread t2 = new Thread(r1, "second");
        t2.start();
    }
}  

在上面的代码中,我使用了一个可运行实例创建了两个线程
现在看一下下面的代码
package com.app.myclasses;
class RunnableTest implements Runnable {
    @Override
    public void run() {
        // TODO Auto-generated method stub

        for (int i = 0; i < 5; i++) {
            System.out.println(i);
        }
    }
}
public class ThreadTesting {
    public static void main(String[] args) {
        RunnableTest r1 = new RunnableTest();
        RunnableTest r2 = new RunnableTest();
        Thread t1 = new Thread(r1, "first");
        t1.start();
        Thread t2 = new Thread(r2, "second");
        t2.start();
    }
}  

在第二段代码中,我创建了两个可运行实例r1和r2,并相应地创建了线程。
那么上述两个代码有什么区别?是否存在内存使用问题或性能问题,或者其中一个实际上不是多线程?
以上文本的英译如下。

没有区别。RunnableTest 不具有状态。 - xehpuk
2个回答

7

方法本地变量隐式线程安全的。因此,在您的情况下,这并不重要,因为i非共享的

考虑这样一个情况:

class RunnableTest implements Runnable {

 int i = 0;

@Override
public void run() {
    // TODO Auto-generated method stub

    for (i = 0; i < 5; i++) {
        System.out.println(Thread.currentThread().getName() + " : " + i);
    }
}

现在,

class ThreadTesting {
    public static void main(String[] args) {
        RunnableTest r1 = new RunnableTest();
        Thread t1 = new Thread(r1, "first");
        t1.start();
        Thread t2 = new Thread(r1, "second");
        t2.start();
    }
}

上述代码将无法给您正确的输出(0-4两次)。输出结果可能是以下内容:
 first : 0
second : 0
first : 1
second : 2
first : 3
second : 4

我们这里有一些实例级别的字段(是共享的)。所以,输出结果并不是您所期望的。
在另一种情况下,实例级别的字段不会在线程之间共享。因为您有两个不同的可运行对象。
如果您想在可运行实例内部进行同步,并且使用了“this”,那么仅处理“一个实例”而不是“2个单独的可运行实例”将是正确的。 注意:在可运行实例上加锁被认为是不好的设计。

0
在您的第一个示例中,您有一个RunnableTest实例,因此任何实例变量都将由两个线程共享。在第二种情况下,有两个实例,因此线程只会共享静态数据。
例如
class RunnableTest implements Runnable {
    static String shared = "Shared static data";
    String instance = "Instance data";
    @Override
    public void run() {
        // TODO Auto-generated method stub

        System.out.println(Thread.currentThread().getName() + " " + shared + " " + instance);
    }
    RunnableTest(String instance) {
        this.instance = instance;
    }
    public static void main(String[] args) {
        RunnableTest r1 = new RunnableTest("instance1");
        Thread t1 = new Thread(r1, "first");
        t1.start();
        Thread t2 = new Thread(r1, "second");
        t2.start();
    }
}  

提供

first Shared static data instance1
second Shared static data instance1

class RunnableTest implements Runnable {
    static String shared = "Shared static data";
    String instance = "Instance data";
    @Override
    public void run() {
        // TODO Auto-generated method stub

        System.out.println(Thread.currentThread().getName() + " " + shared + " " + instance);
    }
    RunnableTest(String instance) {
        this.instance = instance;
    }
    public static void main(String[] args) {
        RunnableTest r1 = new RunnableTest("instance1");
        Thread t1 = new Thread(r1, "first");
        t1.start();
        Thread t2 = new Thread(r1, "second");
        t2.start();
    }
}  

提供

first Shared static data instance1
second Shared static data instance2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接