【发布时间】:2014-05-31 22:22:14
【问题描述】:
假设我有以下课程:
public class BuggyClass {
private String failField = null;
public void create() {
destroy();
synchronized (this) {
failField = new String("Ou! la la!");
}
}
public void destroy() {
synchronized (this) {
failField = null;
}
}
public long somethingElse() {
if (failField == null) {
return -1;
}
return failField.length();
}
}
很容易看出,在上述代码的多线程执行中,我们可以在somethingElse 中得到一个NullPointerExeption。例如,可能是 failField != null 和在返回 failField.length() 之前 destroy 被调用,因此使 failField 变为 null。
我想创建一个多线程程序,在使用BuggyClass 时能够“抛出”NullPointerException。我知道,由于该程序是多线程的,因此可能永远不会发生这种情况,但我想应该有一些更好的测试来增加发生异常的可能性。对吧?
我尝试了以下方法:
final BuggyClass bc = new BuggyClass();
final int NUM_OF_INV = 10000000;
int NUM_OF_THREADS = 5;
ExecutorService executor = Executors.newFixedThreadPool(3 * NUM_OF_THREADS);
for (int i = 0; i < (NUM_OF_THREADS); ++i) {
executor.submit(new Runnable() {
public void run() {
for(int i = 0; i< NUM_OF_INV; i++){
bc.create();
}
}
});
}
for (int i = 0; i < (NUM_OF_THREADS); ++i) {
executor.submit(new Runnable() {
public void run() {
for(int i = 0; i< NUM_OF_INV; i++){
bc.destroy();
}}
});
}
for (int i = 0; i < (NUM_OF_THREADS); ++i) {
executor.submit(new Runnable() {
public void run() {
for(int i = 0; i< NUM_OF_INV; i++){
bc.somethingElse();
}}
});
}
executor.shutdown(); executor.awaitTermination(1, TimeUnit.DAYS);
我使用不同的NUM_OF_INV 和NUM_OF_THREADS 多次执行上述代码(方法),但从未设法获得NullPointerException。
关于如何创建一个增加我在不更改BuggyClass 的情况下获得异常的机会的任何想法?
【问题讨论】:
-
我认为
failField == null被认为是Java 中的单个操作。小手术不多。 -
强制这样的条件非常困难(当然,除非你雇了一个傻瓜——傻瓜有时非常聪明)。
-
不建议自己扔
NullPointerException。 -
String 在 Java 中是不可变的,因此它是线程安全的。任何不可变类都是线程安全的。
-
伙计们:他试图导致(显然)错误代码失败。与字符串是不可变的还是不朽的,或者字符串引用上的
==是否是单个原子操作无关。
标签: java multithreading concurrency synchronized executorservice