使用线程解决文件复制和重命名

现有A、B两个线程,文件夹S中有10张图片,图片名分别为a1.jpg或a1.png、b2.jpg或b2.png、c3..d4..以此类推..k10.jpg或k10.png,A线程任务是往文件夹D中拷贝图片,B线程任务是每有一张图片拷贝进来,需将图片名称改成1.jpg或1.png。。以此类推到10.png或10.jpg,然后程序退出。要求:A线程不能一次拷贝多张图片,B线程不能一次修改多张图片名,即模拟生产者、消费者,拷贝进一个,修改一个名称

这道题目可以使用生产者-消费者模型来实现,其中 A 线程作为生产者,负责向文件夹 D 中拷贝图片;B 线程作为消费者,负责修改拷贝进来的图片名称。

具体实现思路如下:

定义一个共享的队列,用于存储拷贝进来的图片文件名。

A 线程循环遍历文件夹 S 中的图片,每次只拷贝一张图片到文件夹 D 中,并将拷贝的图片文件名加入队列中。

B 线程循环从队列中取出一个图片文件名,将其修改为指定格式,然后保存到文件夹 D 中。

当队列为空时,B 线程结束循环,程序退出。

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Main {

    public static void main(String[] args) {
        // 定义文件夹 S 和 D 的路径
        String srcDir = "/path/to/S";
        String dstDir = "/path/to/D";

        // 定义共享队列,用于存储拷贝进来的图片文件名
        BlockingQueue<String> imageQueue = new LinkedBlockingQueue<>();

        // 定义 A 线程,负责向 D 文件夹中拷贝图片
        Thread threadA = new Thread(() -> {
            // 遍历 S 文件夹中的图片
            for (int i = 1; i <= 10; i++) {
                String srcFile = srcDir + "/a" + i + ".jpg";
                if (!new File(srcFile).exists()) {
                    srcFile = srcDir + "/a" + i + ".png";
                }
                String dstFile = dstDir + "/a" + i + ".jpg";
                if (!new File(dstFile).exists()) {
                    dstFile = dstDir + "/a"".png";
                }
                try {
                    Files.copy(new File(srcFile).toPath(), new File(dstFile).toPath(), StandardCopyOption.REPLACE_EXISTING);
                    // 将拷贝的图片文件名加入队列中
                    imageQueue.put(new File(dstFile).getName());
                } catch (IOException | InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        // 定义 B 线程,负责修改拷贝进来的图片名称
        Thread threadB = new Thread(() -> {
            // 定义计数器,用于计数已经修改的图片数量
            int count = 0;
            while (count < 10) {
                try {
                    // 从队列中取出一个图片文件名
                    String imageName = imageQueue.take();
                    // 修改图片文件名
                    String newImageName = String.format("%d%s", count + 1, imageName.substring(imageName.lastIndexOf('.')));
                    Path oldPath = new File(dstDir, imageName).toPath();
                    Path newPath = new File(dstDir, newImageName).toPath();
                    Files.move(oldPath, newPath, StandardCopyOption.REPLACE_EXISTING);
                    count++;
                } catch (IOException | InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

线程A的逻辑是从S文件夹拷贝图片文件到D文件夹,线程B的逻辑是从D文件夹拿出一个图片文件修改文件名。
可以把D文件夹看成是多线程操作中的临界区资源,是需要锁住的资源,伪代码比如: synchronized File file = new File("c:/d");
并且提供一个方法让A线程和B线程在操作时,能且只能通过我指定的这个方法来获取D文件夹对象来操作,
A线程要向文件夹写入新文件时,若能拿到对象则说明B线程未操作,否则只能先等待B线程先操作完后释放锁;B线程同理