удаление файла в Java при загрузке его в другой поток - PullRequest
2 голосов
/ 17 июня 2010

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

Я даю возможность нескольким потокам добавлять файлы из моей системы.

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

Моя проблема заключается в том, что я хочу, чтобы в минуту, когда получено сообщение об удалении, я жду, пока все потоки, которые являются DL файлом, завершат DL, и ТОЛЬКО чем excute file.delete (). какой лучший способ сделать это?

Я подумал о некоторой базе данных, которая содержит> итерацию и проверку активности потока, но это кажется неуклюжим. Есть ли способ лучше? спасибо

Ответы [ 4 ]

2 голосов
/ 17 июня 2010

Я думаю, что вы можете сделать это проще, чем с помощью базы данных. Я бы поместил тонкий класс-оболочку вокруг File .. a TrackedFile. В нем есть файл, и количество людей, которые его читают. Когда вы удалите, просто перестаньте позволять новым людям захватывать файл и дождитесь, пока счетчик достигнет 0.

Поскольку вы имеете дело со многими потоками, обращающимися к общему состоянию, убедитесь, что вы правильно используете java.util.concurrent

1 голос
/ 17 июня 2010

Я не уверен, что это решает все ваши проблемы, но вот что я имею в виду:

Если предположить, что все операции чтения / записи / удаления выполняются только из одного приложения, механизм синхронизации потоков с использованием блокировок может быть полезен.

Для каждого поступающего нового файла может быть создана новая блокировка чтения / записи (см. ReentrantReadWriteLock в Java). Блокировка чтения должна быть установлена ​​для всех операций чтения, в то время как блокировка записи должна быть установлена ​​для операций записи / удаления. Конечно, когда блокировка получена, вы должны проверить, имеет ли значение эта операция (т. Е. Существует ли файл).

0 голосов
/ 18 июня 2010

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

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

Делая это таким образомразделение чтения файла на отдельные потоки также позволит вам иметь один поток, загружающий определенный файл, и иметь несколько загрузок клиента, получающих данные с одного прохода чтения по файлу.С этим можно реализовать несколько оптимизаций, в зависимости от типа проекта.Если вы это сделаете, убедитесь, что вы не храните слишком много файловых данных в памяти, иначе произойдет очевидное.Но если вы гарантированы характером вашего проекта, что будет мало и / или небольших файлов, которые не будут занимать слишком много памяти, это отличный побочный эффект разделения загрузки файлов в отдельный поток.

Если вы идете по этому пути, используя join (), вы можете использовать вариант join (миллисекунды), если вы хотите, чтобы поток удаления мог ждать определенный период, а затем требовать остановки других потоков (для больших файлов и / или раз).когда доступ ко многим файлам, так что HD идет медленно), если они этого еще не сделали.Просто получите временную метку (now + theDurationYouWantToWait) и присоединитесь (impatientTimestamp-currentTimestamp), и отправьте прерывание всем потокам загрузки файлов в середине цикла, если (currentTimestamp> = impatientTimestamp) - тогда получите потоки загрузки файловпроверьте это в цикле, где они читают данные файла, затем повторно объедините () поток, из которого было прервано соединение (в миллисекундах), и продолжите итерацию объединения (), которую вы выполняли.

0 голосов
/ 17 июня 2010

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

private class DeleteRunnable implements Runnable {
 public void run() {
  while (!done) {
   ArrayList<DeletedObject> tmpList = null;
   synchronized (masterList) {
    tmpList = new ArrayList<DeletedObjects>(masterList);
   }

   for (DeletedObject o : tmpList)
    if (o.waitForReaders(500, TimeUnit.MilliSeconds))
     synchronized (masterList) {
      masterList.remove(o);
     }
  }
 }
}  
...