我有一个带有几个线程的应用程序,它们操作数据并将输出保存在特定目录,Linux或Windows机器上的不同临时文件中。最终需要删除这些文件。
我想要做的是能够更好地分离文件,所以我想通过进程ID和线程ID来做这件事。这将有助于应用程序节省磁盘空间,因为在线程终止时,可以擦除包含该线程文件的整个目录,并使应用程序的其余部分重用相应的磁盘空间。
由于应用程序在JVM的单个实例上运行,我假设它将具有单个进程ID,这将是JVM的进程ID,对吧?
在这种情况下,区分这些文件的唯一方法是将它们保存在一个文件夹中,其名称将与线程ID相关。
这种做法是否合理,或者我应该做些什么呢?
答案 0 :(得分:2)
java.io.File可以create临时文件给你。只要保留与每个线程关联的文件列表,就可以在线程退出时删除它们。如果线程未完成,您还可以将文件标记为delete on exit。
答案 1 :(得分:1)
你是对的,JVM有一个进程ID,该JVM中的所有线程都将共享进程ID。 (JVM可以使用多个进程,但是AFAIK,没有JVM可以这样做。)
JVM可以很好地为多个Java线程重用底层操作系统线程,因此在Java中退出的线程与操作系统级别发生的类似事件之间没有保证相关性。
如果您只需要清理陈旧文件,按创建时间戳排序文件应该可以完成这项工作吗?无需在临时文件名中对任何特殊内容进行编码。
请注意,PID和TID既不能保证增加,也不能保证在出口中保持唯一。操作系统可以自由回收ID。 (实际上,ID必须在重新使用之前包装,但在某些机器上,只有在创建了32k或64k进程后才会发生。
答案 2 :(得分:1)
这种方法似乎最简单的解决方案是扩展Thread - 从未想过我会在那一天看到它。
作为P.T.已经说过,只要线程处于活动状态,线程ID就是唯一的,它们可以并且肯定会被操作系统重用。
因此,不是这样做,而是使用可以在构造中指定的Thread名称并使其简单,只需编写一个小类:
public class MyThread extends Thread {
private static long ID = 0;
public MyThread(Runnable r) {
super(r, getNextName());
}
private static synchronized String getNextName() {
// We can get rid of synchronized with some AtomicLong and so on,
// doubt that's necessary though
return "MyThread " + ID++;
}
}
然后你可以这样做:
public static void main(String[] args) throws InterruptedException {
Thread t = new MyThread(new Runnable() {
@Override
public void run() {
System.out.println("Name: " + Thread.currentThread().getName());
}
});
t.start();
}
你必须覆盖你想要使用的所有构造函数并且总是使用MyThread
类,但是这样你就可以保证一个独特的映射 - 至少2 ^ 64-1(负值也可以很好) )应该绰绰有余。
虽然我仍然认为这不是最好的方法,可能最好创建一个包含所有必要信息的“工作”类,并且可以在不再需要时立即清理文件 - 这样你也可以轻松地使用ThreadPools和co,其中一个线程将执行多个作业。目前,你在一个线程中有业务逻辑 - 这并没有让我觉得特别好的设计。