需要扫描整个计算机的文件,我想启动一个文件。walkFileTree(startingFolder,FileVisitor)。但是,我发现FileVisitor覆盖方法越来越混乱。如果我只启动一个线程,一切都正常,但当我启动第二个或更多线程时,第一个线程的FileVisitor方法被忽略或使用不正确的文件调用。Files. walkFileTree()是一个静态方法。我为每个线程指定一个新的FileVisitor实现,但是没有用。我发现files.walkFileTree()比其他方法快65%。我怎样才能使它多线程化呢?
节日快乐,谢谢。
彼得·耶克维茨
样本代码:
ArrayList<Path> seeds = new ArrayList<>(); // This is where we are going to start looking
private void launchTreeWalkers() {
ArrayList<Path> effectivelyFinalPath = this.seeds; // Physical drives on the computer ie C:\ D:\ E:\ ...
int[] index = new int[1]; // Effectively Final
this.twThreads = new Thread[ effectivelyFinalPath.size() ]; // TreeWalkerThreads
for ( int i=0; i < effectivelyFinalPath.size(); i++ ) {
index[i] = i;
this.twThreads[i] = new Thread( new Runnable() {
@Override
public void run() {
try {
tTreeWalker2( effectivelyFinalPath.get( index[0]) );
} catch ( Exception ex ) {
ex.printStackTrace();
}
}
}
);
this.twThreads[i].setDaemon( true ); // So the thread will die when the parent dies.
this.twThreads[i].setName("Tree Walker");
this.twThreads[i].start();
}
Display.fmt("%1$,d Tree Walker thread%2$s %3$s been started.", box( this.twThreads.length ), Aide.plural(this.twThreads.length), Aide.hasHave( this.twThreads.length ) );
}
/** A walkFileTree thread */
void tTreeWalker( Path startingPath ) throws Exception {
@SuppressWarnings("resource") // java.lang.UnsupportedOperationException when closing FileSystem
FileSystem fileSystem = FileSystems.getDefault();
Files.walkFileTree( fileSystem.getPath( startingPath.toString() ), new FileVisitorImpl());
}
/** */
public class FileVisitorImpl implements FileVisitor<Path> {
@Override // Called before a directory visit.
public FileVisitResult preVisitDirectory( Path directory, BasicFileAttributes attrs ) throws IOException {
Locate.this.folderCountLA.increment(); // Long Adder
if ( isMatch( excludeFolders, directory ))
return FileVisitResult.SKIP_SUBTREE;
Locate.this.foldersSelectedLA.increment();
return FileVisitResult.CONTINUE;
}
@Override // Called after a directory visit is complete.
public FileVisitResult postVisitDirectory( Path dir, IOException exc ) throws IOException {
return FileVisitResult.CONTINUE;
}
@Override // This method is called for each file visited. The basic attributes of the files are also available.
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Locate.this.fileCountLA.increment();
if ( ! isMatch( excludeFiles, file ) ) {
FileOfInterest foi = new FileOfInterest( file );
try {
if (( probZips ) && ( foi.isCompressedFile() )) {
foundFilesQ.put( foi );
//TODO Zip handler goes here
} else if ( isMatch( selectFiles, file ) ) {
Locate.this.filesSelectedLA.increment();
foundFilesQ.put( foi ); // Blocking if the Q is full.
}
} catch ( InterruptedException ex ) { // We do not expect this to ever happen.
ex.printStackTrace();
}
}
return FileVisitResult.CONTINUE;
}
@Override // If the file visit fails for any reason, the visitFileFailed method is called.
public FileVisitResult visitFileFailed( Path file, IOException exc) throws IOException {
if ( ! isMatch( knownFailures, file ) ) { // Ignore known failures
String msg = exc.toString();
if ( msg.contains( "java.nio.file.AccessDeniedException" )) {
Locate.this.accessDeniedLA.increment();
if ( showAccessDenied )
Display.fmt("visitFileFailed %s", exc.toString() );
} else {
Locate.this.failuresLA.increment();
Display.fmt("visitFileFailed %s", exc.toString() );
}
}
return FileVisitResult.CONTINUE;
}
} // End of FileVisitorImpl
1条答案
按热度按时间kupeojn61#
问题解决了。在试图通过创建Effectively Final变量作为数组来欺骗java以用于创建runnable时,我感到很痛苦。当我在测试用例中创建4个线程时,所有4个线程都在同一个驱动器上运行,最后一个进入。它们没有按顺序使用,当时,我在其中创建了runnable。我通过让线程访问AtomicInteger来索引包含驱动器的数组来解决这个问题。我还在线程中创建了FileVisitorImpl。谢谢并祝新年快乐。Peter Jerkewitz