Может ли несколько потоков записывать данные в файл одновременно? - PullRequest
31 голосов
/ 22 декабря 2011

Если вы когда-либо использовали программное обеспечение для загрузки p2p, они могут загрузить файл с многопоточностью и создали только один файл, поэтому мне интересно, как потоки записывают данные в этот файл.Последовательно или параллельно?

Представьте, что вы хотите вывести большую таблицу базы данных в файл, и как сделать эту работу быстрее?

Ответы [ 5 ]

21 голосов
/ 22 декабря 2011

Вы можете использовать несколько потоков для записи в файл, например. файл журнала. но вы должны координировать свои темы, как указывает @Thilo. Либо вам нужно синхронизировать доступ к файлу и записывать только целые записи / строки, либо вам нужна стратегия для распределения областей файла по разным потокам, например восстановление файла с известными смещениями и размерами.

Это редко делается из соображений производительности, поскольку большинство дисковых подсистем работают лучше всего при последовательной записи, а узким местом является дисковый ввод-вывод. Узким местом может быть ЦП для создания записи или строки текста (или сетевого ввода-вывода).

Изображение, которое вы хотите вывести в таблицу большую таблицу базы данных, и как сделать эту работу быстрее?

Последовательная его запись, вероятно, будет самой быстрой.

18 голосов
/ 22 декабря 2011

Пакет Java nio был разработан, чтобы позволить это. Посмотрите, например, на http://docs.oracle.com/javase/1.5.0/docs/api/java/nio/channels/FileChannel.html.

Вы можете отобразить несколько областей одного файла в разные буферы, каждый буфер может быть заполнен отдельно отдельным потоком.

2 голосов
/ 09 ноября 2012

Синхронизированное объявление позволяет сделать это. Попробуйте приведенный ниже код, который я использую в похожем контексте.

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);
        }
    }
}
1 голос
/ 22 декабря 2011

Что это за файл?Зачем вам нужно кормить его с большим количеством потоков?Это зависит от характеристик (я не знаю лучшего слова для этого) использования файла.

Передача файла из нескольких мест по сети (кратко: Torrent-like)

Если вы переносите существующий файл, программа должна

  • , как только он узнает размер файла, создайте его с пустым содержимым: thisпредотвращает последующую ошибку нехватки диска (если не хватает места, при создании, перед загрузкой чего-либо), это также помогает повысить производительность;
  • , если вы хорошо организовали передачу (и почему бы и нет), каждый поток будет отвечать за отдельную часть файла, таким образом, запись в файл будет отличаться,
  • , даже если два потока каким-либо образом выберут одну и ту же часть файла, это не вызовет ошибки, посколькуони записывают одни и те же данные для одних и тех же позиций файла.

Добавление блоков данных в файл (кратко: регистрация)

Если потоки просто добавляются фиксированными илиразличный-Длина информации в файл, вы должны использовать общий поток.Он должен использовать относительно большой буфер записи, чтобы он мог быстро обслуживать клиентские потоки (просто принимая строки) и сбрасывать его из оптимального расписания и размера блока.Он должен использовать выделенный диск или даже компьютер.

Кроме того, может быть несколько проблем с производительностью, поэтому существуют серверов журналирования вокруг, даже дорогие коммерческие.

Чтение и запись случайного времени, случайной позиции (кратко: база данных)

Требуется сложный дизайн, с мьютексами и т. Д. Я никогда не делал такого рода вещи, но я могу представить.Спросите у Oracle некоторые хитрости:)

0 голосов
/ 22 декабря 2011

Вы можете записать несколько потоков в один и тот же файл, но по одному. Все потоки должны будут ввести синхронизированный блок перед записью в файл.

В примере P2P - один из способов его реализации - найти размер файла и создать пустой файл такого размера. Каждый поток загружает различные разделы файла - когда им нужно записать, они войдут в синхронизированный блок - переместите указатель файла, используя поиск и запись содержимого буфера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...