2011-12-22 38 views
29

Nếu bạn đã từng sử dụng phần mềm tải xuống p2p, họ có thể tải xuống tệp có nhiều luồng và họ chỉ tạo một tệp, Vì vậy, tôi tự hỏi cách luồng ghi dữ liệu vào tệp đó. Tuần tự hoặc song song?Nhiều luồng có thể ghi dữ liệu vào một tệp cùng lúc không?

Hãy tưởng tượng rằng bạn muốn đổ một bảng cơ sở dữ liệu lớn vào một tệp và cách làm cho công việc này nhanh hơn?

+13

Có, họ có thể, nhưng bạn thực sự muốn tránh họ làm điều đó cùng một lúc. Cần phải có sự phối hợp nào đó. Nếu bạn đang nói về Bittorrent, tôi nghĩ rằng các công trình bằng cách lắp ráp các khối của offsets được biết đến vào một tập tin có kích thước được biết đến. Điều đó không thể được gọi là tuần tự hoặc song song, nó là "truy cập ngẫu nhiên" nhiều hơn. – Thilo

+0

Câu hỏi tương tự: http://stackoverflow.com/questions/6206472/what-is-the-best-way-to-write-to-a-file-in-a-parallel-thread-in-java – Vadzim

Trả lời

21

Bạn có thể sử dụng nhiều chuỗi ghi vào một tệp, ví dụ: một tệp nhật ký. nhưng bạn phải phối hợp các chủ đề của mình như @Thilo chỉ ra. Bạn cần phải đồng bộ hóa quyền truy cập tệp và chỉ ghi toàn bộ bản ghi/dòng hoặc bạn cần có chiến lược phân bổ các vùng của tệp cho các chủ đề khác nhau, ví dụ: xây dựng lại một tệp có số lượng và kích thước đã biết.

Điều này hiếm khi được thực hiện vì lý do hiệu suất vì hầu hết các hệ thống con đĩa hoạt động tốt nhất khi được ghi vào tuần tự và đĩa IO là nút cổ chai. Nếu CPU để tạo bản ghi hoặc dòng văn bản (hoặc mạng IO) là nút cổ chai nó có thể giúp đỡ.

Hình ảnh mà bạn muốn kết xuất bảng cơ sở dữ liệu lớn thành tệp và cách thực hiện công việc này nhanh hơn?

Viết tuần tự có thể là nhanh nhất.

+0

Sử dụng semaphore –

0

Bạn có thể có nhiều chuỗi ghi vào cùng một tệp - nhưng mỗi lần một chuỗi. Tất cả các chủ đề sẽ cần phải nhập một khối đồng bộ trước khi ghi vào tập tin.

Trong ví dụ P2P - một cách để thực hiện nó là tìm kích thước tệp và tạo tệp trống có kích thước đó. Mỗi luồng tải xuống các phần khác nhau của tệp - khi họ cần viết chúng sẽ nhập một khối được đồng bộ - di chuyển con trỏ tệp bằng cách tìm kiếm và ghi nội dung của bộ đệm.

+0

"Tất cả các chủ đề sẽ cần phải nhập một khối đồng bộ trước khi ghi vào tập tin." Vâng, họ không * có *. Nhưng bạn sẽ không thích đầu ra sau đó, có thể được xen kẽ theo những cách vui nhộn. – Thilo

18

Gói Java nio được thiết kế để cho phép điều này. Hãy xem ví dụ tại http://docs.oracle.com/javase/1.5.0/docs/api/java/nio/channels/FileChannel.html.

Bạn có thể ánh xạ một số vùng của một tệp vào các bộ đệm khác nhau, mỗi bộ đệm có thể được điền riêng biệt bằng một chuỗi riêng biệt.

+2

+1 Nếu một người muốn thực hiện "phần mềm tải xuống p2p" này trong Java, điều đó có vẻ giống như một API tốt để sử dụng. – Thilo

1

Loại tệp này là gì? Tại sao bạn cần phải ăn nó với nhiều chủ đề hơn? Nó phụ thuộc vào các đặc tính (Tôi không biết từ tốt hơn cho nó) của việc sử dụng tệp.

Chuyển một tập tin từ một số nơi qua mạng (viết tắt: Torrent-like)

Nếu bạn đang chuyển một tập tin hiện có, chương trình nên

  • càng sớm, như nó được biết kích thước của tập tin, tạo ra nó với nội dung trống: điều này ngăn ngừa lỗi sau đĩa (nếu không có đủ dung lượng, nó sẽ xuất hiện lúc tạo, trước khi tải xuống bất kỳ thứ gì), nó cũng giúp hiệu suất;
  • nếu bạn tổ chức thực hiện tốt chuyển giao (và tại sao không), mỗi chủ đề sẽ chịu trách nhiệm một phần riêng biệt của tập tin, do đó nộp viết sẽ rõ rệt,
  • thậm chí nếu bằng cách nào đó hai đề chọn phần cùng của tập tin, nó sẽ không gây ra lỗi, bởi vì chúng viết cùng một dữ liệu cho cùng một vị trí tập tin.

Phụ thêm khối dữ liệu vào một tập tin (viết tắt: khai thác gỗ)

Nếu đề chỉ gắn thêm thông tin cố định hoặc khác nhau-lenght vào một tập tin, bạn nên sử dụng một chủ đề phổ biến. Nó nên sử dụng một bộ đệm ghi tương đối lớn, vì vậy nó có thể phục vụ các chủ đề của khách hàng một cách nhanh chóng (chỉ lấy các chuỗi), và tuôn ra nó lên kế hoạch tối ưu và kích thước khối. Nó nên sử dụng đĩa chuyên dụng hoặc thậm chí máy tính.

Ngoài ra, có thể có một số vấn đề về hiệu suất, đó là lý do tại sao có máy chủ ghi nhật ký xung quanh, ngay cả những thương mại đắt tiền.

Đọc và viết thời gian ngẫu nhiên, vị trí ngẫu nhiên (viết tắt: cơ sở dữ liệu)

Nó đòi hỏi thiết kế phức tạp, với mutexes vv, tôi không bao giờ thực hiện công cụ này kinda, nhưng tôi có thể tưởng tượng. Hỏi Oracle về một số thủ thuật :)

2

Tuyên bố đồng bộ hóa cho phép thực hiện việc này. Hãy thử các mã dưới đây mà tôi sử dụng trong một bối cảnh tương tự.

package hrblib; 

import java.io.*; 

public class FileOp { 

    static int nStatsCount = 0; 

    static public String getContents(String sFileName) { 

     try { 
      BufferedReader oReader = new BufferedReader(new FileReader(sFileName)); 
      String sLine, sContent = ""; 
      while ((sLine=oReader.readLine()) != null) { 
       sContent += (sContent=="")?sLine: ("\r\n"+sLine); 
      } 
      oReader.close(); 
      return sContent; 
     } 
     catch (IOException oException) { 
      throw new IllegalArgumentException("Invalid file path/File cannot be read: \n" + sFileName); 
     } 
    } 
    static public void setContents(String sFileName, String sContent) { 
     try { 
      File oFile = new File(sFileName); 
      if (!oFile.exists()) { 
       oFile.createNewFile(); 
      } 
      if (oFile.canWrite()) { 
       BufferedWriter oWriter = new BufferedWriter(new FileWriter(sFileName)); 
       oWriter.write (sContent); 
       oWriter.close(); 
      } 
     } 
     catch (IOException oException) { 
      throw new IllegalArgumentException("Invalid folder path/File cannot be written: \n" + sFileName); 
     } 
    } 
    public static synchronized void appendContents(String sFileName, String sContent) { 
     try { 

      File oFile = new File(sFileName); 
      if (!oFile.exists()) { 
       oFile.createNewFile(); 
      } 
      if (oFile.canWrite()) { 
       BufferedWriter oWriter = new BufferedWriter(new FileWriter(sFileName, true)); 
       oWriter.write (sContent); 
       oWriter.close(); 
      } 

     } 
     catch (IOException oException) { 
      throw new IllegalArgumentException("Error appending/File cannot be written: \n" + sFileName); 
     } 
    } 
} 
Các vấn đề liên quan