我正在使用多个线程将文件上传到服务器。 Java Applet 负责显示 UI。最初我使用 ThreadPoolExecutor 启动 5 个线程并为它们分配 5 个文件。每次上传后,我都会收到来自服务器的通知。当一个线程完成执行时,另一个新线程被分配一个文件,直到所有文件都上传到服务器。
基本代码结构如下:
i> 正在从负责处理上传功能的 Java Applet 调用方法 startUpload()。
class Upload extends Runnable{
...............................
..............................
public void startUpload() {
............................... //other initialisations done
int waitTime = 500;
Random random = new Random();
ExecutorService executor = new ThreadPoolExecutor(5, 5, 50000L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(300));
while (it.hasNext()) {
int time = random.nextInt(1000);
waitTime += time;
newFile = new File((String) it.next());
executor.execute(new Runnable() {
@Override
public void run() {
try{
Thread.sleep(wait);
}
catch(Exception e){
}
processFile1(newFile);
}
});
}
try {
Thread.sleep(waitTime);
executor.shutdown();
executor.awaitTermination(waitTime, TimeUnit.MILLISECONDS);
} catch (Exception e) {
}
}
我目前面临的问题。
i> UI 仅在所有文件上传完毕后才更新。在中间阶段,UI 处于挂起状态。 EDT 似乎要进入阻塞状态。
当我使用 Thread 类、通知/ sleep 来实现相同的功能时,用于 UI 渲染的相同代码工作正常。我将代码更改为 ThreadPoolExecutor,因为我在很多博客/文章中看到它是从 Java 5.0 版实现多线程的更好方法。
ii> 我在 ThreadPoolExecutor 中注意到的另一件事是,当我上传大小为 1KB 的多个文件(用于测试目的)时,如果我从上面的代码中删除所有 wait() ,则以下行分配一个新文件但是多个线程每次总是上传同一个文件。
newFile = new File((String) it.next());
但是在添加 sleep() 和 run() 时,多个线程将不同的文件上传到服务器。
上面的代码有实现上的问题吗?
最佳答案
问题 1:newFile
是一个(静态的?)字段而不是局部变量。
你想要的是确保 newFile
的本地捕获在每个循环中都是不同的。因此,它应该看起来更像:
while(it.hasNext()) {
final File newFile = new File((String) it.next());
executor.execute(new Runnable() {
@Override
public void run() {
processFile1(newFile); // Local only to this iteration of the loop.
}
}
}
您的代码全部包装在 Runnable
实例中。你能告诉我们这是从哪个线程调用的吗?如果它在 EDT 上,那么这就可以解释为什么 UI 会锁定。
一个小问题是您的迭代器缺少泛型。理论上,您应该遍历字符串集合:
Collection<String> listOfFiles = ...
Iterator<String> it = listOfFiles.iterator();
while(it.hasNext()) {
String filename = it.next(); // No cast necessary
}
关于java - ThreadPoolExecutor 的实现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8075421/