文件重命名时的线程安全性

时间:2012-07-21 07:35:48

标签: java multithreading thread-safety

我对以下代码有些疑虑。

public class Task implements Runnable {

String filePath = "C:\\Backup\\test.xml";

@Override
public void run() {

    File file = new File(filePath);

    try {

        System.out.println(Thread.currentThread() + " Renaming " + FileUtil.changeFileExtention(file));
        Thread.sleep(20000);
        System.out.println(Thread.currentThread() + " Renaming Back " + FileUtil.changeFileExtention(file));

    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

}

这里的`FileUtil'是一个类。

public class FileUtil {

public static File changeFileExtention(File file) throws Exception {

    File newFile = null;

    int extIndex = file.getName().lastIndexOf(".");

    String ext = getExtentionFromFile(file);

    System.out.println("File Extention is [" + ext + "] for file [" + file.getName() + "].");

    if (ext.equalsIgnoreCase(".xml")) {

        newFile = buildChangedFile(file, extIndex, ".txt");

    } else if (ext.equalsIgnoreCase(".proc")) {

        newFile = buildChangedFile(file, extIndex, ".xml");
    }

    file.renameTo(newFile);

    return newFile;

}

public static String getExtentionFromFile(File file) throws Exception {

    String fileName = file.getName();

    int extIndex = fileName.lastIndexOf(".");

    if (extIndex != -1) {

        return fileName.substring(extIndex);

    } else {

        String msg = "File extention not found for file [" + fileName + "]";
        System.out.println(msg);
        throw new Exception(msg);
    }
}

private static File buildChangedFile(File file, int extIndex, String targetExtention) throws Exception {

    String fileName = file.getName();

    File renamedFile = null;

    if (file.exists()) {

        String newFileName = fileName.substring(0, extIndex) + targetExtention;

        System.out.println("New File name -" + newFileName);

        String fullPathWithName = file.getParent() + "/" + newFileName;

        renamedFile = new File(fullPathWithName);

    } else {

        String msg = "File not exisit in location [" + file.getAbsolutePath() + "]";
        System.out.println(msg);
        throw new Exception(msg);
    }

    return renamedFile;
}

}

这是我的测试类 -

public class Test {


public static void main(String[] args) {

    Thread thread1 = new Thread(new Task());
    Thread thread2 = new Thread(new Task());
    Thread thread3 = new Thread(new Task());

    thread1.start();
    thread2.start();
    thread3.start();
}

}

我需要的是,如果一个线程接受该文件,其他线程需要忽略该文件。我不太清楚这里的线程进程并且有些混乱。

  1. 我需要在synchronize阻止吗?
  2. 中进行重命名过程
  3. 我的FileUtil方法是线程安全的吗?
  4. 由于Task类为每个线程创建一个新实例,每个线程都应该有自己的file对象。既然在这种情况下在堆中创建对象会被共享吗?或者一个线程在堆中有自己的对象堆栈吗?
  5. 如果两个线程试图同时重命名该文件会发生什么? (我应该制作我的工艺方法synchronize吗?)
  6. 高度感谢您的帮助以消除我的困惑。提前谢谢大家。

1 个答案:

答案 0 :(得分:1)

显然,如果你有一个文件要更改名称,则不需要多个线程。否则,这看起来像典型的消费者 - 生产者问题。作为替代解决方案,您可以使用blockingQueue结构来使用线程安全性。一个(或多个)线程将文件名添加到队列中,所有使用者线程都使用文件名来更改其名称。

您可以查看LinkedBlockingQueue