私はそれを使用するために必要なことだと思うAtomicInteger
ThreadFactoryではなく、私は自分自身にそれを証明しようとしているとき、私はハードに失敗しました。
new ThreadFactory() {
private int threadId = 0; <---- AtomicInteger preferred
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
t.setName("my-thread-" + (threadId++)); <--- dangerous code
return t;
}
}
いくつかの要求が来た場合は、スレッドファクトリは、それらを処理するためにスレッドを生成し、生成時に、そこに可能性があり、その間のギャップも競合状態がこっそりかもしれません。
私は私の理論を証明するために、次のコードで試してみましたが、それはとまったく起こっていない2_000コアスレッド。
@Slf4j
public class ThreadFactoryTest {
private ConcurrentHashMap<String, Thread> threadIdThreadMap = new ConcurrentHashMap<>();
private ThreadPoolExecutor myExecutor = new ThreadPoolExecutor(2000, 2000, 30, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100000), new ThreadFactory() {
private int threadId = 0;
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
t.setName("my-thread-" + (threadId++));
if (threadIdThreadMap.contains(t.getName())) {
log.error("already existed");
System.err.println(myExecutor);
myExecutor.shutdownNow();
} else threadIdThreadMap.put(t.getName(), t);
return t;
}
}, new ThreadPoolExecutor.AbortPolicy());
@Test
public void testThreadFactory() throws Exception {
for (int i = 0; i < 100; ++i) {
new Thread(() -> runOneHundredJobs()).start();
}
Thread.sleep(1000000);
myExecutor.shutdown();
myExecutor.awaitTermination(100, TimeUnit.MINUTES);
}
private void runOneHundredJobs() {
log.info("{} starting to submit tasks", Thread.currentThread().getName());
for (int i = 0; i < 100; ++i) {
myExecutor.execute(() -> {
while (100 < System.currentTimeMillis()) {
try {
Thread.sleep(1000);
if (Math.random() > 0.99) break;
System.out.println(Thread.currentThread().getName());
System.out.println(myExecutor);
} catch (Exception e) {
}
}
} );
}
}
}
私はいつも「ことを知っているので、愚かな質問のように見える、それはマルチスレッド競合状態のためのギャップを作成するのは難しいです」。
すべてのヘルプ/手がかりが理解されるであろう。)
更新
途中、@StephenCと@Slawに沿って助けを本当に感謝します。私はそこにいくつかのポイントを誤解していること、申し訳ありません。(
そうnewThread
で実装する必要があるスレッドセーフウェイ、その後、私の場合には、AtomicInteger
必要とされます。そして私はStephenCからの引用がしたいです:
競合状態を実証するための失敗は、それが存在しないという意味ではありません。
ThreadFactoryでのAtomicIntegerを使用することが必要ですか?
これは、工場出荷時のオブジェクトがどのように使われるかに依存します。
あなたは、各インスタンスに異なるファクトリオブジェクトを指定すると
ThreadPoolExecutor
、その後、工場のための(実際の)同時実行性の要件は、executorが、それをどのように使用するかに依存します。javadoc内の文が存在しない場合には、あなたは、ソースコードを検討する必要があります。私がチェックしていませんが、私は(への呼び出しを含むスレッドプールの拡張を疑うnewThread
ミューテックスの内部で起こります)。私の疑いが正しければ、このユースケースは、スレッドセーフであることがファクトリオブジェクトを必要としません。UPDATE -私は今チェックして、そして私の疑惑だった間違った(Javaの8&12用)。
newThread
コールは、新しい作成時に作られWorker
たオブジェクトを、そのミューテックスを保持している間に行われていません。そのため、あなたのnewThread
方法は、あまりにも、この文脈では、スレッドセーフであることが必要です。ファクトリオブジェクトは、他のもの(例えば、別のエグゼキュータ)と共有されているなら、あなたは正しいです:あなたの
newThread
方法は、スレッドセーフである必要があります。
私は、競合状態を表示しようとするあなたのコードを見ていませんが、私の心に、それは、このことについてに行くための最善の方法ではありません。コードの検査と推論は、より良い方法です。競合状態を実証するための失敗は、それが存在しないという意味ではありません。