阿坤973 2023-05-26 09:15 采纳率: 28.6%
浏览 102
已结题

如何使用java来实现多线程的读写文件操作

现在想用java实现以下功能:
将某目录下的文件读取出来,经过业务处理之后,再按照一定条件写成新文件。
目前我的思路是这样的
1、要可以配置读的线程数,每个线程读一个文件,然后将读取到的结果放到多个队列(也不一定要多个队列,只希望高效一些)中
2、要可以配置写线程数,每个线程写一个文件,从队列中取。
3、要保证异常机制,也就是程序挂了,下次启动的时候能够继续处理

其中这边的多个线程如何协同读写,已经程序在某个时刻挂掉了,然后重启的时候如何能恢复之前的状态,这一块我还不会设计,有什么好的设计思路吗?

  • 写回答

9条回答 默认 最新

  • 创意程序员 2023-05-26 09:33
    关注

    1、多线程要考虑并发读写同一个文件的问题。既然这样,可以主线程列出待读写的文件列表W,然后使用线程安全的方式如Collections.synchronizedList(list),线程池里每个线程领取一个任务(文件),并且将这个文件移入正在处理的文件列表P中(如CopyOnWriteArrayList,这个是写的时候加锁),按要求处理完,再将这个文件从正在处理的文件列表,移到已处理完的文件列表中。再获取下一个文件进行处理,直到列表中所有文件都处理完。
    2、可以在每次文件列表有变化时、或者定时(如每n秒)、或者在暂停处理时,将上述待处理文件列表和正在处理的文件列表序列化以后写入磁盘文件S。如果程序中断,重新启动程序时,主线程除了前面提到的工作,增加一步读取该磁盘文件S,如果该文件存在,反序列化两个文件列表的内容,以这两个列表为准。等待所有线程处理完以后,再清理掉这个磁盘文件。
    3、考虑程序中断后继续处理,待处理的文件可能有变化,与磁盘文件S中存的列表有差异,因此各线程处理文件时,要考虑文件实际不存在的异常情况。主线程要在列出待读写的文件列表P以后,更新磁盘文件S中反序列化得到的列表。
    线程池关键部分代码如下:

            // 创建n个线程
            int n = 10;
            ThreadPoolExecutor executor = new ThreadPoolExecutor(n, n, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
            for (int i = 0; i < n; i++) {
                executor.execute(() -> {
                      // 每个线程要做的事情
                      // 领取任务、读写文件等
                });
            }
            //关闭线程池
            executor.shutdown();
            //等待线程池中所有线程执行完毕
            try {
                executor.awaitTermination(1, TimeUnit.MINUTES);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    

    纯人工想法,其它部分如有问题,可以和我私信交流

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 6月2日
  • 创建了问题 5月26日