2015-07-07 11 views
5

Tôi đang chạy chương trình nơi tôi tải xuống các tệp lớn, phân tích cú pháp chúng và sau đó ghi dữ liệu tôi đã trích xuất từ ​​tệp vào một tệp khác."Chuỗi chủ đề" có phải là một giải pháp tồi cho ứng dụng Java này không?

Tệp mất nhiều thời gian để tải xuống và phân tích cú pháp nhưng tác vụ viết chỉ mất trung bình một phút. Giải pháp của tôi mà tôi đã ném cùng nhau là có ba bản cố định của ba luồng.

ExecutorService downloadExecutor = Executors.newFixedThreadPool(3); 
ExecutorService parseExecutor = Executors.newFixedThreadPool(3); 
ExecutorService writeExecutor = Executors.newFixedThreadPool(3); 

Chủ đề trong nhóm tải xuống tải xuống, sau đó gửi tên tệp làm tham số. Điều này được thực hiện trong chính chuỗi đó. Chuỗi tải xuống sau đó tải xuống một tệp khác từ danh sách các URL của tệp. Khi một chuỗi phân tích cú pháp đã hoàn thành việc phân tích cú pháp dữ liệu tôi muốn từ tệp, sau đó nó gửi một luồng mới chứa dữ liệu vào luồng viết, sau đó nó được ghi vào tệp .csv.

Câu hỏi của tôi là nếu có giải pháp thanh lịch hơn cho vấn đề này. Tôi đã không thực sự thực hiện nhiều luồng phức tạp. Vì tôi có nhiều tệp để tải xuống và phân tích cú pháp, tôi không muốn bất kỳ chuỗi nào không hoạt động bất kỳ lúc nào. Ý tưởng một lần nữa, là kể từ khi phân tích cú pháp một tập tin có thể mất một lúc, tôi cũng có thể làm cho các chủ đề riêng biệt dành cho tải về những tập tin đầu tiên.

Trả lời

8

Tại sao không sử dụng chỉ một nhóm Chủ đề. Tải xuống, phân tích cú pháp và lưu phải đợi cho nhau để có thể tách riêng các tác vụ tốt nhất là sử dụng một luồng cho mỗi tệp.

+0

Vâng, như tôi đã đề cập, những tệp này có thể có kích thước một vài GB. Việc phân tích cú pháp có thể mất hơn 30 phút đến một giờ để hoàn thành. Logic của tôi là thay vì chờ đợi cho các tập tin được phân tích cú pháp trước khi tải về một tập tin mới, thay vào đó dành riêng cho chủ đề mà sẽ tiếp tục tải về các tập tin và khi nó đã đi xuống, gửi tập tin đó để threadpool này. Điều này sẽ dẫn đến một hàng đợi các tập tin đang chờ phân tích cú pháp. Nghe có vẻ hiệu quả hơn với tôi. – GreenGodot

+0

Thực hiện điều đơn giản nhất đầu tiên @GreenGodot. Hoạt động tổng thể của bạn được giới hạn bởi phần chậm nhất anyway ... bạn có thực sự muốn hàng trăm tập tin GB chờ đợi trên đĩa? – Dennis

+0

Nếu nó giúp ích, tôi sẽ xóa tệp đã tải xuống bằng cách sử dụng File.delete() khi tôi đã phân tích xong tệp. nó không giải quyết được vấn đề không gian một cách hoàn toàn nhưng điều đó có giúp ích gì không? – GreenGodot

2

Đây không phải là hành vi không tốt vì nhiều nhà phát triển thực hiện loại mã hóa tương tự. Nhưng có điều bạn cần lưu ý.

Số một, Bạn không thể mong đợi hiệu suất tăng chỉ vì bạn có nhiều chuỗi hơn. Có số lượng chủ đề tối ưu dựa trên không có CPU.

Số Hai, Bạn phải đảm bảo cách xử lý ngoại lệ.

Số ba, Bạn phải chắc chắn rằng bạn có thể tắt tất cả các nhóm luồng trong một sự kiện mà bạn cần phải dừng ứng dụng.

2

Vì vậy, vấn đề của bạn có hai khía cạnh:

  1. Tính ràng buộc
  2. IO bị ràng buộc

Đọc và viết vào tập tin được IO bị ràng buộc. IO không đồng bộ là tốt nhất cho các nhiệm vụ ràng buộc IO. Java có AsynchronousFileChannel cho phép bạn đọc và ghi các tệp mà không phải lo lắng về các nhóm luồng nơi tiếp tục đạt được thông qua trình xử lý hoàn thành. Complete Example.

AsynchronousFileChannel ch = AsynchronousFileChannel.open(path); 
    final ByteBuffer buf = ByteBuffer.allocate(1024); 
    ch.read(buf, 0, 0, 
      new CompletionHandler() { 
       public void completed(Integer result, Integer length){   
        .. 
       } 

       public void failed(Throwable exc, Integer length) { 
        .. 
       } 
      } 
    ); 

Và bạn làm tương tự cho viết, bạn chỉ cần viết thư cho kênh

ch.write(... 

Không cho phân tích các tập tin, đó là một nhiệm vụ tính toán ràng buộc, và bạn sẽ nhận được lõi CPU của bạn nóng cho rằng, bạn có thể gán một hồ bơi thread bằng số lõi bạn có.

executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()) 

Bây giờ điều cần nhớ là: bạn cần kiểm tra mã và thử nghiệm mã đồng thời là khó. Nếu bạn không thể chứng minh tính chính xác của nó, đừng làm điều đó.

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