2012-06-19 34 views
8

Tôi có tệp CSV rất lớn (1GB +), nó có 100.000 dòng.Cách chia nhỏ tệp CSV thành nhiều phần và đọc các đoạn đó song song trong mã Java

Tôi cần viết chương trình Java để phân tích từng dòng từ tệp CSV để tạo nội dung cho yêu cầu HTTP gửi đi.

Nói cách khác, tôi cần gửi 100.000 yêu cầu HTTP tương ứng với các dòng trong tệp CSV. Nó sẽ rất dài nếu tôi làm điều này trong một chủ đề duy nhất.

Tôi muốn tạo 1000 chuỗi để làm i) đọc một dòng từ tệp CSV, ii) tạo yêu cầu HTTP có nội dung chứa nội dung của dòng đọc và iii) gửi yêu cầu HTTP ra và nhận phản hồi.

Bằng cách này, tôi cần phải chia tệp CSV thành 1.000 đoạn và các đoạn đó sẽ không có các dòng chồng lên nhau.

Cách tốt nhất để thực hiện quy trình tách này là gì?

+1

* Tôi có một tệp CSV rất lớn (1GB +), nó có 100.000 dòng * cho các máy tính ngày nay nó to hơn một chút. Có nhiều chủ đề hơn đáng kể so với CPU là một sai lầm nếu bạn có thể bão hòa tất cả các CPU. Cuối cùng nó sẽ bị ràng buộc trong sự ra đi IO, cũng gửi tấn yêu cầu đồng thời đến một máy chủ không phải là rất khôn ngoan, trừ khi bạn cố tình cố gắng DoS. – bestsss

Trả lời

7

Đọc một tệp duy nhất tại nhiều vị trí đồng thời sẽ không cho phép bạn đi nhanh hơn (nhưng nó có thể làm chậm bạn xuống đáng kể).

Thay vì đọc tệp từ nhiều luồng, hãy đọc tệp từ một chuỗi và song song với việc xử lý của các dòng này. Một chuỗi đơn sẽ đọc dòng CSV của bạn, và đặt mỗi dòng trong một hàng đợi. Nhiều luồng làm việc sau đó sẽ lấy dòng tiếp theo từ hàng đợi, phân tích cú pháp, chuyển đổi thành yêu cầu và xử lý yêu cầu đồng thời khi cần. Việc chia tách công việc sau đó sẽ được thực hiện bởi một chuỗi duy nhất, đảm bảo rằng không có dòng hoặc chồng chéo bị thiếu.

+0

Có thể thực hiện thao tác chia tách thành nhiều phần cùng kích thước trước khi đọc tệp không? Nếu vậy, sau khi các tập tin được tách ra, nhìn chằm chằm nhiều chủ đề để đọc khối song song sẽ nhanh hơn một thread duy nhất đọc toàn bộ tập tin, phải không? – JuliaLi

+0

@JuliaLi Không, không thực sự: các tệp lớn thường chiếm nhiều khối được đặt gần nhau trên đĩa.Vì đĩa nhanh hơn nhiều khi truy cập các khối liên tiếp vì không cần phải định vị lại đầu từ, đọc một tệp lớn từ đĩa sẽ nhanh hơn nhiều khi được thực hiện liên tục. – dasblinkenlight

4

Bạn có thể có một chuỗi đọc dòng CSV và xây dựng Danh sách các dòng đã đọc. Khi điều này đạt đến một số giới hạn, ví dụ: 100 dòng để chuyển thông tin này đến một hồ bơi có kích thước cố định để gửi theo yêu cầu.

Tôi nghi ngờ rằng trừ khi máy chủ của bạn có 1000 lõi, bạn có thể thấy rằng việc sử dụng 10-100 yêu cầu đồng thời nhanh hơn.

+0

Tùy thuộc vào thời gian để nhận phản hồi HTTP. Nếu các máy chủ có liên quan chậm, hầu hết các luồng sẽ đợi I/O. – biziclop

+0

Nếu mạng hoặc máy chủ chậm, việc sử dụng kích thước lô lớn hơn hoặc yêu cầu nhỏ hơn có thể cải thiện thời gian tải. Không thể nói điều gì là tối ưu mà không thử nghiệm nó. Quan điểm của tôi là; không giả sử nhiều chủ đề càng tốt. –

+1

Đó là ý của tôi. Vì ứng dụng của bạn có nhiều khả năng bị ràng buộc I/O, một công thức cố định dựa trên số lõi sẽ không hoạt động, bạn phải thử nghiệm với những gì hoạt động tốt nhất. (Hoặc viết một hệ thống thích nghi, có lẽ là quá phức tạp.) – biziclop

1

Có một chủ đề đọc từng dòng tệp và mỗi dòng đọc, đăng một tác vụ vào ExecutorService để thực hiện yêu cầu HTTP cho từng dòng.

Đọc tệp từ nhiều chuỗi sẽ không hoạt động, để đọc dòng thứ nhất n, trước hết bạn phải đọc tất cả các mục khác. (Nó có thể hoạt động theo lý thuyết nếu tệp của bạn chứa bản ghi có chiều rộng cố định, nhưng CSV không phải là định dạng chiều rộng cố định.)

+0

bạn có thể phỏng đoán kết thúc của dòng khi bạn biết các cột, có thể thực hiện được nhưng hầu như không đáng để thử. Vì vậy, nếu có nhiều mảng đĩa và ánh xạ tập tin nhiều chủ đề sẽ làm việc (cho phần đọc) – bestsss

+0

Có thể làm một hoạt động tách để chia thành nhiều phần trong cùng một kích thước trước khi đọc các tập tin? Nếu vậy, sau khi tập tin được tách ra, nhìn chằm chằm nhiều chủ đề để đọc khối song song. – JuliaLi

2

đọc CSV tập tin trong chủ đề duy nhất khi bạn nhận được dòng đại biểu dòng này với một trong những Thread sẵn trong hồ bơi bằng cách xây dựng các đối tượng của Runnable Task của bạn và vượt qua nó để Executors'ssubmit(), mà sẽ được thực hiện đồng bộ.

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

     String fName = "C:\\Amit\\abc.csv"; 
     String thisLine; 
     FileInputStream fis = new FileInputStream(fName); 
     DataInputStream myInput = new DataInputStream(fis); 
     ExecutorService pool=Executors.newFixedThreadPool(1000); 
     int count = 0; // Concurrent request to Server barrier 

     while ((thisLine = myInput.readLine()) != null) { 
      if (count > 150) { 
       try { 
        Thread.sleep(100); 
        count = 0; 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 

      pool.submit(new MyTask(thisLine)); 
      count++; 
     } 

    } 
} 

Đây Task:

class MyTask implements Runnable { 
     private String lLine; 
     public MyTask(String line) { 
      this.lLine=line; 

     } 

     public void run() { 
      // 1) Create Request lLine 
      // 2) send the HTTP request out and receive response 
     } 
} 
0

Java 8, dự kiến ​​phát hành trong tháng này, sẽ được cải thiện hỗ trợ cho điều này thông qua con suối song song và lambdas. tutorial của Oracle trên song song luồng có thể là điểm khởi đầu tốt.

Lưu ý rằng lỗ hổng ở đây là quá nhiều song song.Đối với ví dụ về việc truy xuất URL, có thể là một ý tưởng tốt để có số lượng cuộc gọi song song thấp. Quá nhiều song song có thể ảnh hưởng đến không chỉ băng thông và trang web bạn đang kết nối, nhưng bạn cũng sẽ gặp rủi ro khi chạy hết các bộ mô tả tệp, đó là một tài nguyên giới hạn nghiêm ngặt trong hầu hết các môi trường nơi java chạy.

Một số khung có thể giúp bạn là Netflix 'RxJavaAkka. Hãy lưu ý rằng các khung công tác này không tầm thường và sẽ nỗ lực học hỏi.

Các vấn đề liên quan