我认为这是必须使用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
,则执行如何使用它的工厂(实际)并发需求将依赖于。在没有的javadoc语句中,你将需要检查源代码。我没有检查,但我怀疑线程池(包括调用的膨胀newThread
)发生一个互斥体。如果我的怀疑是正确的,那么这个用例不需要工厂对象是线程安全的。
更新 -我现在已经查看过,我怀疑是不正确(用于Java 8和12)。将newThread
创建一个新的呼叫时作出Worker
对象,同时持有互斥锁未完成。因此,你的newThread
方法必须是线程安全的在这方面了。
如果一个工厂对象与其他事物(例如,另一个执行人)共享,那么你是正确的:你的newThread
方法需要是线程安全的。
我没有看过你的代码,以尽量展现竞争条件,但在我看来,这不是去了解的最佳方式。代码检查和推理是一种更好的方式。未能表现出竞争条件并不意味着它不存在。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句