【问题标题】:deleting a file in java while uploading it in other thread在其他线程中上传文件时在java中删除文件
【发布时间】:2010-06-17 17:24:40
【问题描述】:

我正在尝试构建一个半文件共享程序,当每台计算机都充当服务器和客户端时。

我为多个线程提供了从我的系统中 DL 文件的选项。

另外,我有一个可以接收删除消息的用户界面。

我的问题是,我希望在收到删除消息的那一刻,我等待作为 DL 文件的所有线程完成 DL,并且仅执行 file.delete()。 最好的方法是什么?

我想到了一些保存 > 并迭代并检查线程是否处于活动状态的数据库,但它看起来很笨拙。有没有更好的办法? 谢谢

【问题讨论】:

  • 我记得这是 Joel 在最初的土豚规格中采用的方法。

标签: java multithreading networking download


【解决方案1】:

我认为您可以比使用数据库更简单地做到这一点。我会在 File.. 一个 TrackedFile 周围放置一个薄包装类。它里面有文件,并计算有多少人正在阅读它。当您删除时,停止允许新人抓取文件,并等待计数变为 0。

由于您正在处理访问共享状态的许多线程,请确保正确使用 java.util.concurrent

【讨论】:

    【解决方案2】:

    我不确定这是否能解决您的所有问题,但这是我的想法:

    假设所有读/写/删除操作只发生在同一个应用程序中,使用锁的线程同步机制可能很有用。

    对于每个到达的新文件,可以创建一个新的读/写锁(参见 Java 的 ReentrantReadWriteLock)。所有读操作都应该获取读锁,而写/删除操作应该获取写锁。当然,在获取锁的时候,你应该检查操作是否仍然有意义(即文件是否仍然存在)。

    【讨论】:

    • 我喜欢它。当单个进程管理文件时,ReentrantReadWriteLock 是一个比尝试使用数据库或文件系统锁等其他工具进行同步更简单的解决方案。
    【解决方案3】:

    如果您必须等待所有读者完成,您的删除事件处理线程(可能是您的 UI)将变得无响应。而是将删除排队并定期轮询可以处理的删除。您可以使用:

    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);
         }
      }
     }
    }  
    

    【讨论】:

      【解决方案4】:

      如果您要稍微重构您的设计,以便不在同一个线程中完成从磁盘加载文件和将文件上传到客户端,您可以通过锁定新线程来等待文件停止被访问从读取此文件,然后遍历从该文件读取的所有线程,并对每个线程执行一次 join() 操作。只要文件读取线程在加载文件后直接终止,迭代就会在最后一个线程不再读取文件的那一刻结束,你就可以开始了。

      以下段落基于您不断重复读取文件数据多次的假设,即使读取线程都在相同的一般时间范围内进行读取,因为这听起来像是您正在做的事情。

      这样做,将文件读取分离到单独的线程中,还允许您让单个线程加载特定文件,并让多个客户端上传从文件的单个读取传递中获取数据。您可以使用它实现几种优化,具体取决于它用于什么类型的项目。如果这样做,请确保不要在内存中保留太多文件数据,否则会发生明显的事情。但是,如果您的项目性质保证不会占用太多内存的文件很少和/或小文件,那么将文件加载分离到单独的线程中会产生很大的副作用。

      如果你走这条使用 join() 的路线,你可以使用 join(milliseconds) 变体,如果你希望删除线程能够等待一段时间然后要求其他线程停止(对于大文件和/或很多文件被访问的时候,所以 HD 变慢了),如果他们还没有的话。只需获取 (now + theDurationYouWantToWait) 和 join(impatientTimestamp-currentTimestamp) 的时间戳,然后在 if(currentTimestamp >= impatientTimestamp) 上向循环中间的所有文件加载线程发送中断 - 然后让文件加载线程在他们正在读取文件数据的循环中检查它,然后重新加入()加入(毫秒)中止的线程并继续你正在进行的加入()迭代。

      【讨论】:

        猜你喜欢
        • 2011-12-02
        • 2017-06-21
        • 1970-01-01
        • 1970-01-01
        • 2023-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多