Java: ExecutorService 错误
Java: ExecutorService error
我对 ExecutorService 有点陌生,但遇到了问题。我有这个 class:
@Override
public void updateAvatar(final MultipartFile multipartFile, final String speakerId) {
final GridFS avatarGfs = new GridFS(getTemplate().getDb(), SPEAKER_AVATAR_COLLECTION);
// Remove all sizes
avatarGfs.remove(new BasicDBObject(SPEAKER_ID_FIELD, speakerId));
System.out.println("hello from updateAvatar");
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.execute(new Runnable() {
public void run() {
for (SpeakerAvatarSize size : SpeakerAvatarSize.values()) {
try {
System.out.println("calling saveAvatar");
saveAvatar(multipartFile, speakerId, size, avatarGfs);
} catch (IOException e) {
LOG.error("SpeakerRepository#updateAvatar", e);
}
}
}
});
executorService.shutdown();
System.out.println("shut down threads");
}
我在编辑当前用户头像以及添加另一个头像时遇到此错误。好像只加了1个头像:
Exception in thread "pool-2-thread-1" java.lang.IllegalStateException: File has been moved - cannot be read again
at org.springframework.web.multipart.commons.CommonsMultipartFile.getInputStream(CommonsMultipartFile.java:123)
at util.ImageScaleUtil.scale(ImageScaleUtil.java:26)
at impl.SpeakerRepository.saveAvatar(SpeakerRepository.java:97)
at impl.SpeakerRepository.access[=12=]0(SpeakerRepository.java:28)
at impl.SpeakerRepository.run(SpeakerRepository.java:81)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
提前致谢!
您使用了 executor 服务,因此 saveAvatar 函数可能会 运行 在您的 updateAvater 完成后。那时,Web 框架可能已经清理了 multipartFile。
要等待执行器服务,您只需添加:
executorService.shutdown();
System.out.println("shut down threads");
try {
executorService.awaitTermination(60, TimeUnit.SECONDS);
} catch (InterruptedException ignored) {
}
顺便说一下,您创建了一个执行器服务,每个查询都有 3 个线程,并且只使用其中的一个线程。由于您必须等待任务完成,因此在那里使用执行程序服务确实没有意义。
@Override
public void updateAvatar(final MultipartFile multipartFile, final String speakerId) {
final GridFS avatarGfs = new GridFS(getTemplate().getDb(), SPEAKER_AVATAR_COLLECTION);
// Remove all sizes
avatarGfs.remove(new BasicDBObject(SPEAKER_ID_FIELD, speakerId));
System.out.println("hello from updateAvatar");
for (SpeakerAvatarSize size : SpeakerAvatarSize.values()) {
try {
System.out.println("calling saveAvatar");
saveAvatar(multipartFile, speakerId, size, avatarGfs);
} catch (IOException e) {
LOG.error("SpeakerRepository#updateAvatar", e);
}
}
}
或者如果你想将 for 循环并行到 运行,那么你可以使用 this answer:
@Override
public void updateAvatar(final MultipartFile multipartFile, final String speakerId) {
final GridFS avatarGfs = new GridFS(getTemplate().getDb(), SPEAKER_AVATAR_COLLECTION);
// Remove all sizes
avatarGfs.remove(new BasicDBObject(SPEAKER_ID_FIELD, speakerId));
System.out.println("hello from updateAvatar");
Parallel.For(SpeakerAvatarSize.values(), size -> {
try {
System.out.println("calling saveAvatar");
saveAvatar(multipartFile, speakerId, size, avatarGfs);
} catch (IOException e) {
LOG.error("SpeakerRepository#updateAvatar", e);
}
});
}
我对 ExecutorService 有点陌生,但遇到了问题。我有这个 class:
@Override
public void updateAvatar(final MultipartFile multipartFile, final String speakerId) {
final GridFS avatarGfs = new GridFS(getTemplate().getDb(), SPEAKER_AVATAR_COLLECTION);
// Remove all sizes
avatarGfs.remove(new BasicDBObject(SPEAKER_ID_FIELD, speakerId));
System.out.println("hello from updateAvatar");
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.execute(new Runnable() {
public void run() {
for (SpeakerAvatarSize size : SpeakerAvatarSize.values()) {
try {
System.out.println("calling saveAvatar");
saveAvatar(multipartFile, speakerId, size, avatarGfs);
} catch (IOException e) {
LOG.error("SpeakerRepository#updateAvatar", e);
}
}
}
});
executorService.shutdown();
System.out.println("shut down threads");
}
我在编辑当前用户头像以及添加另一个头像时遇到此错误。好像只加了1个头像:
Exception in thread "pool-2-thread-1" java.lang.IllegalStateException: File has been moved - cannot be read again
at org.springframework.web.multipart.commons.CommonsMultipartFile.getInputStream(CommonsMultipartFile.java:123)
at util.ImageScaleUtil.scale(ImageScaleUtil.java:26)
at impl.SpeakerRepository.saveAvatar(SpeakerRepository.java:97)
at impl.SpeakerRepository.access[=12=]0(SpeakerRepository.java:28)
at impl.SpeakerRepository.run(SpeakerRepository.java:81)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
提前致谢!
您使用了 executor 服务,因此 saveAvatar 函数可能会 运行 在您的 updateAvater 完成后。那时,Web 框架可能已经清理了 multipartFile。
要等待执行器服务,您只需添加:
executorService.shutdown();
System.out.println("shut down threads");
try {
executorService.awaitTermination(60, TimeUnit.SECONDS);
} catch (InterruptedException ignored) {
}
顺便说一下,您创建了一个执行器服务,每个查询都有 3 个线程,并且只使用其中的一个线程。由于您必须等待任务完成,因此在那里使用执行程序服务确实没有意义。
@Override
public void updateAvatar(final MultipartFile multipartFile, final String speakerId) {
final GridFS avatarGfs = new GridFS(getTemplate().getDb(), SPEAKER_AVATAR_COLLECTION);
// Remove all sizes
avatarGfs.remove(new BasicDBObject(SPEAKER_ID_FIELD, speakerId));
System.out.println("hello from updateAvatar");
for (SpeakerAvatarSize size : SpeakerAvatarSize.values()) {
try {
System.out.println("calling saveAvatar");
saveAvatar(multipartFile, speakerId, size, avatarGfs);
} catch (IOException e) {
LOG.error("SpeakerRepository#updateAvatar", e);
}
}
}
或者如果你想将 for 循环并行到 运行,那么你可以使用 this answer:
@Override
public void updateAvatar(final MultipartFile multipartFile, final String speakerId) {
final GridFS avatarGfs = new GridFS(getTemplate().getDb(), SPEAKER_AVATAR_COLLECTION);
// Remove all sizes
avatarGfs.remove(new BasicDBObject(SPEAKER_ID_FIELD, speakerId));
System.out.println("hello from updateAvatar");
Parallel.For(SpeakerAvatarSize.values(), size -> {
try {
System.out.println("calling saveAvatar");
saveAvatar(multipartFile, speakerId, size, avatarGfs);
} catch (IOException e) {
LOG.error("SpeakerRepository#updateAvatar", e);
}
});
}