我创建了一个类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);
}
}
我在类Core中使用它如下:
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以使用匿名的runnable类时:
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)是线程安全的。在这种情况下,为什么变量线程是安全的?提前谢谢。
答案 0 :(得分:3)
在第一个示例中,您有一个Runnable实例(在所有线程中共享)。在你的第二个例子中,你有10个Runnable实例,每个Thread有1个实例(没有共享,因此,线程安全)。
答案 1 :(得分:1)
线程安全不依赖于类是否具有名称。在第一种情况下,您在所有线程中共享命名类的实例;您可以轻松地与您的第二个匿名课程做同样的事情!
此外,您可以在匿名类的实例之间共享在外部作用域中声明的final
个变量。尽管变量必须是final,但并不意味着它的实例将是 immutable 。在这种情况下,匿名类肯定是非线程安全的。
所以标题问题的答案是“不,并非所有匿名类都是线程安全的”。无论是否命名,您都需要明确设计具有线程安全性的类。
答案 2 :(得分:0)
匿名或不跟匿的类与线程安全无关。
匿名类就像普通类一样,除了它的源不存在于自己的.java
文件中(以及其他一些非常小的东西)。
答案 3 :(得分: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);