繁体   English   中英

Java-使用线程池同时发送多个文件时出错

[英]Java - Error sending multiple files concurrently using threadpool

我正在尝试同时将一些文件发送到rest api。 试图实现这个答案

public class UploadThread implements Runnable {

    private File file;

    public UploadThread(File file) {
        this.file = file;
    }

    @Override
    public void run() {
        try {
            String url = // api url

            URL server = new URL(url);
            HttpURLConnection connection = (HttpURLConnection) server.openConnection();

            // setting request properties here

            connection.connect();

            OutputStream out = connection.getOutputStream();
            FileInputStream in = new FileInputStream(file);

            try {
              // write to outputstream

            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                out.close();
                in.close();

                if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                    // error handling here
                }

                connection.disconnect();            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public class UploadTest {

    public static void main(String[] args) throws Exception {

        List<File> files = Files.walk(Paths.get("/home/random"))
                                .filter(Files::isRegularFile)
                                .map(Path::toFile)
                                .collect(Collectors.toList());

        ExecutorService executorService = Executors.newFixedThreadPool(5);

        for(File file : files) {
            Runnable worker = new UploadThread(file);

            executorService.execute(worker);
        }

        executorService.shutdown();

        while(!executorService.isTerminated()) {
            //
        }

        System.out.println("upload finished....");

    }
}

我在random目录中有10个文件。

当我执行此操作时,第一个文件的发送次数与我在Executors.newFixedThreadPool()方法中分配的线程数完全相同。

如果我分配5个线程,则第一个文件(每次执行都不同)将发送5次,而其余文件则仅发送一次! 对于10个线程,它将发送10次!

如何只发送一个文件多次,而其余文件却不发送? 我在代码中做错了什么?

编辑 :我将文件发送到的api在Tomcat 8上使用Jersey 这是文件的处理方式。

在资源上

@Path("file")
public class MyResource {

    private StorageManager storageManager;

    public MyResource() {
        this.storageManager = new StorageManager();
    }

    @GET
    @Path("upload")
    @Consumes(MediaType.APPLICATION_OCTET_STREAM)
    public Response upload(InputStream inputStream) {
        return this.storageManager.upload(inputStream);
    }
}

并且StorageManager类是

public class StorageManager {

    public Response upload(InputStream inputStream) {

        // handling file upload here
        // this method is called 5 or 10 times for one file

        // return some response
    }
}

对于单个文件,这可以正常工作。 我已经使用REST客户端上传了数百个文件,并且每次都能正常运行。 但是对于并发请求,对于任何一个文件(第一个文件)都会多次调用此upload()方法。

尝试过您的代码,似乎工作正常。 顺便说一下,不需要将Path映射到File因为使用Files.copy可以轻松地将Path的内容复制到OutputStream

public class UploadThread implements Runnable {

   private Path file;

   public UploadThread(Path file) {
    this.file = Objects.requireNonNull(file);
   }

 @Override
  public void run() {
    try {
        String url = // api url

        URL server = new URL(url);
        HttpURLConnection connection = (HttpURLConnection) server.openConnection();

        // setting request properties here

        connection.connect();

        try (OutputStream out = connection.getOutputStream()) {
            Files.copy(file, out);
          } finally {
            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                // error handling here
            }

            connection.disconnect(); 
          }           
    } catch (Exception e) {
        e.printStackTrace();
    }
  }
}

您也可以放弃for和'while'循环:

public static void main(String[] args) throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(5);
    Files.walk(Paths.get("/home/random"))
                            .filter(Files::isRegularFile)
                            .map(UploadThread::new)
                            .forEach(executorService::execute);

    executorService.shutdown();
    System.out.println("upload finished....");
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM