我正在使用多个线程将文件上传到服务器。 Java Applet负责显示UI。最初,我使用ThreadPoolExecutor启动5个线程,并为其分配5个文件。每次上传后,我都会从服务器收到通知。当线程完成执行时,将为另一个新线程分配一个文件,直到所有文件都上载到服务器。

基本代码结构如下:

从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类时,相同的UI呈现代码工作正常,notify/sleep实现相同的功能。我将代码更改为ThreadPoolExecutor,因为在任何博客/文章中都没有看到它是从Java ver 5.0实现多线程的更好方法。

ii>我在使用ThreadPoolExecutor注意到的另一件事是,当我上传多个大小为1KB的文件(出于测试目的)时,如果我从上述代码中删除了所有的wait(),则以下行分配了一个新文件,但相同文件总是每次都由多个线程上载。

newFile =新文件((String)it.next());

但是,在与run()一起添加sleep()时,多个线程将不同的文件上传到服务器。

上面的代码有实现问题吗?

最佳答案

问题1:newFile是一个(static?)字段,而不是局部变量。

您要确保每个循环的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/

10-11 12:53
查看更多