2 回答

TA貢獻1827條經(jīng)驗 獲得超8個贊
是否有必要在 ThreadFactory 中使用 AtomicInteger?
這將取決于工廠對象的使用方式。
如果您為每個實例提供不同的工廠對象,
ThreadPoolExecutor
那么工廠的(實際)并發(fā)要求將取決于執(zhí)行程序如何使用它。如果 javadoc 中沒有語句,您將需要檢查源代碼。我沒有檢查過,但我懷疑線程池的擴展(包括對 的調(diào)用newThread
)發(fā)生在互斥量內(nèi)。如果我的懷疑是正確的,那么這個用例不需要工廠對象是線程安全的。更新- 我現(xiàn)在已經(jīng)檢查過了,我的懷疑是不正確的(對于 Java 8 和 12)。該
newThread
調(diào)用是在創(chuàng)建新Worker
對象時進行的,而在持有互斥鎖時不會進行。因此,您的newThread
方法在此上下文中也需要是線程安全的。如果工廠對象與其他事物(例如另一個執(zhí)行程序)共享,那么您是正確的:您的
newThread
方法需要是線程安全的。
我沒有查看您的代碼來嘗試顯示競爭條件,但在我看來,這不是解決此問題的最佳方法。代碼檢查和推理是更好的方法。未能證明競爭條件并不意味著它不存在。

TA貢獻2065條經(jīng)驗 獲得超14個贊
我正在使測試更簡單,以使預(yù)期的結(jié)果從水下浮出水面。
通過下面的測試,預(yù)期的線程大小很1000明顯,而使用通常int會給出一個less大?。ㄔ谖业?macOS 中為 994、996、999),但并非總是如此。
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;
private AtomicInteger atomicThreadId = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
t.setName("my-thread-" + (threadId++));
// uncomment this line, the thread size will be less than 1000
t.setName("my-thread-" + (atomicThreadId.getAndIncrement()));
threadIdThreadMap.put(t.getName(), t);
return t;
}
}, new ThreadPoolExecutor.AbortPolicy());
@Test
public void testThreadFactory() throws Exception {
for (int i = 0; i < 50; ++i) {
new Thread(() -> runOneHundredJobs()).start();
}
Thread.sleep(1000000);
myExecutor.shutdown();
myExecutor.awaitTermination(100, TimeUnit.MINUTES);
}
private void runOneHundredJobs() {
for (int i = 0; i < 20; ++i) {
myExecutor.execute(() -> {
while (100 < System.currentTimeMillis()) {
try {
Thread.sleep(1000);
log.warn("count: {}", threadIdThreadMap.size());
} catch (Exception e) {
}
}
});
}
}
}
添加回答
舉報