#java #multithreading #synchronization #thread-safety
#java #многопоточность #синхронизация #безопасность потоков
Вопрос:
Я записываю в файл через несколько потоков, поэтому я использую следующий код:
synchronized (this) {
BufferedWriter bw = new BufferedWriter(
new FileWriter(path, true));
bw.write(data);
}
и мне интересно в образовательных целях, как я могу использовать какой-нибудь синхронизатор (семафор, обратный отсчет, циклический барриер, фазер или обменник), чтобы, по сути, добиться того же: безопасной многопоточной записи.
Спасибо
Комментарии:
1. Ну, вам нужно узнать, что представляет собой каждый из них, решить, какой из них использовать, и использовать их 😉 Боюсь, что ваш вопрос слишком широк — слишком много возможных ответов — на самом деле, на эту тему можно было бы написать книги. Отправная точка: java.util.concurrent JavaDocs
Ответ №1:
Честно говоря, гораздо лучший, почти тавтологический способ записи из нескольких источников одному и тому же автору — использовать (блокирующую) очередь. Таким образом, все потоки могут отбрасывать свои сообщения в очередь, а поток записи может выбирать сообщения из очереди и записывать их в файл. Как правило, это проще реализовать, а также более эффективно
— редактировать —
Пример:
public class MyQueueableWriter implements Runnable {
private BlockingQueue<Msg> q = new BlockingQueue();
private FileOutputStream fis = ...;
private volatile boolean running = true;
public MyQueueableWriter(FileOutputStream fis) {
this.fis = fis;
}
public void run() {
try {
while (running) {
Message m = q.take();
fis.write(...);
}
fis.close();
} catch (IOException iox) {
...
}
}
public void addMsg(Msg m) {
q.put(m);
}
public void stop() {
running = false;
}
}
Затем добавление в очередь:
public class EnqueueMsgRunnable implements Runnable {
MyQueueableWriter q = ...;
q.put(myMessage);
q.put(myMessage2);
}
Затем просто
for (int i =0; i < numSources; i ) {
EnqueueMsgRunnable r = new EnqueueMsgRunnable(...);
new Thread(r).start();
}
Комментарии:
1. Хм, звучит интересно. Не могли бы вы показать мне простой пример того, как это реализовать, чтобы я мог попробовать это самостоятельно?
2. @Daniel в JavaDocs есть пример производителя-потребителя для BlockingQueue . В вашем случае потребитель будет записывать в файл, в то время как производители записывают в очередь.