1

我创建了一个类 UnSafeTask:

package com.threads;

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class UnsafeTask implements Runnable {
    private Date startDate;

    @Override
    public void run() {
        startDate = new Date();
        System.out.printf("Starting Thread: %s : %s\n", Thread.currentThread().getId(), startDate);
        try {
            TimeUnit.SECONDS.sleep((int) Math.rint(Math.random() * 10));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.printf("Thread Finished: %s : %s\n", Thread.currentThread().getId(), startDate);
    }    
}

我在一个核心类中使用它,如下所示:

package com.threads;

import java.util.concurrent.TimeUnit;

public class Core {

    public static void main(String[] args) {
        UnsafeTask task = new UnsafeTask();

        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(task);
            thread.start();
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

结果与预期一致(变量由线程共享)。当我按如下方式重构 Core 以使用匿名可运行类时:

package com.threads;

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class Core {

    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new Runnable() {
                Date startDate = new Date();

                @Override
                public void run() {
                    startDate = new Date();
                    System.out.printf("Starting Thread: %s : %s\n", Thread.currentThread().getId(), startDate);
                    try {
                        TimeUnit.SECONDS.sleep((int) Math.rint(Math.random() * 10));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.printf("Thread Finished: %s : %s\n", Thread.currentThread().getId(), startDate);    
                }    
            });
            thread.start();
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

现在变量 (startDate) 是线程安全的。为什么在这种情况下变量线程是安全的?提前致谢。

4

4 回答 4

3

在第一个示例中,您有一个 Runnable 实例(在所有线程之间共享)。在第二个示例中,您有 10 个 Runnable 实例,每个线程 1 个实例(不共享,因此是线程安全的)。

于 2012-11-30T03:17:22.910 回答
1

线程安全不取决于类是否有名称。在第一种情况下,您在所有线程之间共享一个命名类的实例;您可以轻松地在第二堂匿名课上做同样的事情!

final此外,您可以在匿名类的实例之间共享在外部范围中声明的变量。尽管变量必须是 final 的,但这并不意味着它的实例是不可变的。在这种情况下,匿名类肯定是非线程安全的。

因此,您的标题问题的答案是“不,并非所有匿名类都是线程安全的”。无论是否命名,您都需要在考虑线程安全的情况下显式设计您的类。

于 2012-11-30T03:21:52.897 回答
0

请注意,您的第二个示例与第一个示例的细微修改相同:

public static void main(String[] args) {

    for (int i = 0; i < 10; i++) {
        // Task object instantiation now inside for loop:
        UnsafeTask task = new UnsafeTask();   
        Thread thread = new Thread(task);
于 2013-05-06T21:17:57.107 回答
0

一个类是否匿名与线程安全无关。

匿名类就像一个普通类,除了它的源不在它自己的.java文件中(以及其他一些非常小的东西)。

于 2012-11-30T03:26:54.993 回答