我的Java代码中存在使用BlockingQueue的潜在竞争条件,我想知道如何修改代码以避免它:
private static BlockingQueue<FileToFTP> ftpQueue = new LinkedBlockingQueue<FileToFTP>();
private static boolean shuttingDown = false;
private static FileToFTP pendingFile = null;
private static int uploadsPending = 0;
private static Thread ftpThread = new Thread(new Runnable() {
public void run() {
try {
for(;;) {
FileToFTP f2f = ftpQueue.take(); // this blocks until there is something to take
// FIXME: If the main thread takes over right
// at this instant, then uploadsRemaining()
// is not correct!!
uploadsPending = 1;
int qs = ftpQueue.size();
logIt(qs, f2f);
pendingFile = f2f;
if(!doUploadFile(f2f.getPath(), f2f.getFilename(), f2f.getRenameTo(), f2f.isBinary())) {
if(shuttingDown) {
log.info("Upload " + f2f + " failed!");
} else {
ftpQueue.offer(f2f); // put it back on to retry later
}
uploadsPending = 0;
} else {
pendingFile = null;
uploadsPending = 0;
}
if(qs == 0) logIt("");
}
} catch (InterruptedException consumed) {
// Allow thread to exit
}
}
});
public static int uploadsRemaining() {
return ftpQueue.size() + uploadsPending;
}
请参阅代码中的“FIXME”评论。谢谢!
答案 0 :(得分:1)
也许我误解了你想要的东西,但听起来你可能最好用ExecutorService
来实际运行。您可以使用Exectors.newSingleThreadExecutor()
或Executors.newFixedThreadPool(2)
创建它们(2是要使用的线程数的示例)。
然后Runnable
上可以.execute
或.submit
ExecutorService
。 submit
将返回Future<T>
对象,该对象可用于跟踪提交给ExecutorService的特定作业的状态。
话虽如此,您可能需要创建一个新类来执行此操作,因为Runnable
/ Callable
类需要在其中包含FileToFTP
变量。 (旁注:我试图避免内部课程,所以如果你想知道为什么我没有建议这样做......)
然后问题变成&#34;如何判断有多少文件待处理?&#34;不幸的是,唯一简单的方法是使它成为另一个类的静态属性...使用静态get / set方法或作为public / protected属性。 AtomicInteger
是理想的选择,因此您可能需要考虑在调用类中使用一个作为受保护的静态实例。它有专用的递增/递减命令以及调整值并返回它的命令。