Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 并行流无法用于将多个文件上载到aws s3_Java_Amazon S3_Java 8 - Fatal编程技术网

Java 并行流无法用于将多个文件上载到aws s3

Java 并行流无法用于将多个文件上载到aws s3,java,amazon-s3,java-8,Java,Amazon S3,Java 8,以下方法用于将文件并行上载到AWS S3,但不会进行并行处理。上传30个文件需要30秒,上传50个文件需要50秒。 我不确定为什么parallel()流在我的用例中不起作用。任何指点都将不胜感激 public ConcurrentHashMap<String, String> uploadMyFiles(MultipartFile[] files, String prefix) { ConcurrentHashMap<String, String> map = n

以下方法用于将文件并行上载到AWS S3,但不会进行并行处理。上传30个文件需要30秒,上传50个文件需要50秒。 我不确定为什么parallel()流在我的用例中不起作用。任何指点都将不胜感激

public ConcurrentHashMap<String, String> uploadMyFiles(MultipartFile[] files, String prefix) {
    ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();
    Stream.of(files).parallel().forEach(file -> {
        String fStatus =  uploadMyFile(file, prefix);                   
        map.put(file.getOriginalFilename(), fStatus);
    }); 

    return fileStatusMap;
}


public String uploadMyFile(final MultipartFile multipartFile, String prefix) {
    try {
        final File file = convertMPartFileToFile(multipartFile);
        uploadToMyBucket("mybucket", file, prefix);

    } catch (final AwsServiceException exception) {         
    
        return exception.getMessage()
    }
    return "OK";
}

private File convertMPartFileToFile(final MultipartFile multipartFile) {
    final File file = new File(multipartFile.getOriginalFilename());
    try (final FileOutputStream outputStream = new FileOutputStream(file)) {
        outputStream.write(multipartFile.getBytes());
    } catch (final IOException ex) {
        LOGGER.error("log error here");
    }
    return file;
}

private String uploadToMyBucket(final String bucket, final File file, String fileKey) {

    PutObjectResponse putObjectResult = s3Client
            .putObject(PutObjectRequest.builder().bucket(bucket).key(fileKey).build(), RequestBody.fromFile(file));
    final URL myfileUrl = s3Client.utilities().getUrl(GetUrlRequest.builder().bucket(bucket).key(fileKey).build());

    return myfileUrl.toString();
}
公共ConcurrentHashMap uploadMyFiles(多部分文件[]文件,字符串前缀){ ConcurrentHashMap=新的ConcurrentHashMap(); Stream.of(files).parallel().forEach(file->{ 字符串fStatus=uploadMyFile(文件,前缀); map.put(file.getOriginalFilename(),fStatus); }); 返回fileStatusMap; } 公共字符串uploadMyFile(最终MultipartFile MultipartFile,字符串前缀){ 试一试{ 最终文件文件=convertMPartFileToFile(多部分文件); uploadToMyBucket(“mybucket”,文件,前缀); }捕获(最终AwsServiceException异常){ 返回异常。getMessage() } 返回“OK”; } 私有文件convertMPartFileToFile(最终多部分文件多部分文件){ 最终文件=新文件(multipartFile.getOriginalFilename()); try(final FileOutputStream outputStream=新FileOutputStream(文件)){ write(multipartFile.getBytes()); }捕获(最终IOEX){ LOGGER.error(“此处记录错误”); } 返回文件; } 私有字符串上传到Tomybucket(最终字符串存储桶、最终文件文件、字符串文件密钥){ PutObjectResponse putObjectResult=s3Client .putObject(PutObjectRequest.builder().bucket(bucket).key(fileKey).build(),RequestBody.fromFile(file)); 最终URL myfileUrl=s3Client.utilities().getUrl(GetUrlRequest.builder().bucket(bucket).key(fileKey.build()); 返回myfileUrl.toString(); }
我建议将
TransferManager
ExecutorService
一起使用,如下例所示


一般情况下,并行任何代码的步骤(一般情况下,AWS不起作用)

  • 您需要一个
    ThreadPool
    ,您可以将
    Callable
    的集合提交给它进行处理
  • 将可调用的
    集合提交到
    线程池的一段代码。每个可调用线程都将在线程池中的线程中执行
  • Future
    集合中检索结果的代码段
  • 这可以通过这个例子天真地实现

      public class S09 {
    
      public static void main(String[] args) {
        demoParallel();
      }
    
      public static void demoParallel() {
        ExecutorService eService = Executors.newFixedThreadPool(5);
        String[] myArr = new String[] {"A", "B", "C"};
        Stream.of(myArr)
            .parallel()
            .map(S09::generateCallable)
            .map(eService::submit)
            .map(S09::obtainFuture)
            .forEach(System.out::println);
      }
    
      public static void demoMethod() {}
    
      private static Callable<String> generateCallable(final String input) {
        return () -> {
          System.out.println(
              "I am waiting here, " + Thread.currentThread() + " for Input String " + input);
          Thread.sleep(5000); // someExpensiveOperationHere
          return "Return Value of " + input;
        };
      }
    
      private static String obtainFuture(Future<String> futureString) {
        try {
          return futureString.get(10, TimeUnit.SECONDS);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
          e.printStackTrace();
        }
        return null;
      }
    }
    
    公共类S09{
    公共静态void main(字符串[]args){
    demoParallel();
    }
    公共静态void demoParallel(){
    ExecutorService eService=Executors.newFixedThreadPool(5);
    字符串[]myArr=新字符串[]{“A”、“B”、“C”};
    溪流(myArr)
    .parallel()
    .map(S09::GenerateCalable)
    .map(电子服务::提交)
    .map(S09::获取未来)
    .forEach(System.out::println);
    }
    公共静态void demoMethod(){}
    私有静态可调用generateCallable(最终字符串输入){
    返回()->{
    System.out.println(
    “我在这里等待,”+Thread.currentThread()+”表示输入字符串“+Input);
    Thread.sleep(5000);//这里有些昂贵的操作
    返回“返回值”+输入;
    };
    }
    私有静态字符串获取未来(未来未来字符串){
    试一试{
    返回futureString.get(10,时间单位为秒);
    }捕获(InterruptedException | ExecutionException | TimeoutException e){
    e、 printStackTrace();
    }
    返回null;
    }
    }
    
    请在uploadMyFileA中完整地展示代码,但是s3句柄是否能够接收来自多个线程的请求(例如,它是否只通过一个单线程工作线程提供请求)?这是一段时间以来,我与API工作,认为有必要为一个线程本地句柄的S3Advess全代码转移管理器有一个最低限度的限制-5MB每部分除了最后一部分。在我的例子中,每个文件都小于1MB。所以技术上我不能用it@mark-多端口加载阈值和最小上载部件大小可配置OK。你认为这会提高性能吗?此外,我还需要在上传结束时返回每个文件上传的状态(失败或成功)对此有何想法?我正在尝试,但我刚刚注意到AWS SDK java2版本还不支持TransferManager,我现有的S3Client使用java2,我无法使用java2 s3客户端创建TransferManager!非常感谢。我已经试过这个代码了。我甚至使用了AWS异步客户机,并提交了他们的完整的未来。它有一点改进,但没有太多改进。请参考java示例回答中的另一个问题,并行流也可以通过在单独的线程中运行每个任务来实现相同的效果?在这种情况下,除非有人想管理线程,否则我们真的需要使用callable吗?