我有一个ScheduledThreadPoolExecutor
有4个活动线程。它充满了一堆任务,每个任务处理一大块物品。
每个任务必须有3个回调:每个已处理项目的开始,结束和一个。
每个回调都会在我的数据库中触发更新。这是一项长期运作的任务。
这是一段示例代码,应该说明我正在做的事情:
public static void main(String[] args) throws InterruptedException {
ScheduledThreadPoolExecutor executor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(4);
Consumer<String> processed = (String o) -> {
System.err.println("PROCESSED: " + o);
try { Thread.sleep(10); }
catch (Exception e) { e.printStackTrace(); }
};
for(int i=0; i<10; i++) {
executor.schedule(
new ChunkTask("task"+i, processed),
500,
TimeUnit.MILLISECONDS
);
}
}
public static class ChunkTask implements Runnable {
String taskId;
Consumer<String> processedCallback;
public ChunkTask(String taskId, Consumer<String> processedCallback) {
this.taskId = taskId;
this.processedCallback = processedCallback;
}
@Override
public void run() {
for(int i=0; i<50; i++) {
processedCallback.accept(taskId+" "+i);
}
}
}
我只是省略了开始和结束回调,因为它与处理过的回调基本相同。
如您所见,我创建了一个Consumer
对象。其中有一个Thread.sleep(10)
来模拟数据库访问。所有4个线程并行调用此对象。
我想知道这是否是线程安全的。 在我看来,Consumer
只是一个无状态对象,使用无状态方法。虽然你可以多次同时调用它。
我是对的吗?
答案 0 :(得分:2)
是的,您的消费者没有任何状态,因此它是线程安全的。它使用的唯一共享对象是System.err
,它本身是线程安全的。
当然,在实际代码中,线程安全性取决于您的操作,而不是打印到System.err
。如果您使用共享数据库服务并且此服务不是线程安全的,那么您将遇到问题。