Java中线程的终止条件
我已经编写了一个多线程Java应用程序,它从一个目录中读取大量.jar文件。这个应用程序产生多个线程,每个线程读取一堆jar文件。识别此应用程序的停止条件时遇到问题。如何确定所有文件都已读取 下面是一个snippet函数,该函数通过run()方法为每个线程调用Java中线程的终止条件,java,multithreading,concurrency,Java,Multithreading,Concurrency,我已经编写了一个多线程Java应用程序,它从一个目录中读取大量.jar文件。这个应用程序产生多个线程,每个线程读取一堆jar文件。识别此应用程序的停止条件时遇到问题。如何确定所有文件都已读取 下面是一个snippet函数,该函数通过run()方法为每个线程调用 import java.io.*; import java.util.Enumeration; import java.util.jar.*; import java.util.zip.ZipEntry; import java.
import java.io.*;
import java.util.Enumeration;
import java.util.jar.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipException;
import java.io.FilenameFilter;
public class ArchiveFileTest implements Runnable {
private static boolean stopAll = false;
private static int threadNumber = 0;
private int myNumber = 0;
public ArchiveFileTest () {
myNumber = threadNumber;
threadNumber++;
}
public static boolean setStopAll () {
return setStopAll(true);
}
public static boolean setStopAll (boolean b) {
stopAll = b;
return stopAll;
}
public static String[] listFiles (File parentDir,final String ext1,final String ext2,final String ext3,final String ext4) {
String allFiles[] = parentDir.list(new FilenameFilter() {
public boolean accept(File pDir, String fName) {
if (fName.endsWith("."+ext1) || fName.endsWith("."+ext2) || fName.endsWith("."+ext3) || fName.endsWith("."+ext4)) return true;
else return false;
}
});
for (int i=0; i<allFiles.length; i++)
allFiles[i] = parentDir.getAbsolutePath() + File.separator + allFiles[i];
return allFiles;
}
public ZipFile getMyZipFile (File parentDir) {
String fn[] = listFiles(parentDir, "jar", "zip", "war", "rar");
int fileNum = myNumber % fn.length;
ZipFile zFile = null;
for (int i=0; i<fn.length; i++) {
String jFile = fn[(fileNum + i)%fn.length];
try {
zFile = new ZipFile(jFile);
break;
} catch (IOException e) {
setStopAll();
}
}
return zFile;
}
public void doStuff() throws Exception {
File dName = new File("/home/sqatest/chander/sample-files");
final int N_TIMES = 15;
final int N_FILES = 500;
int counter = 0;
int fCount = 0;
if (!dName.isDirectory() || !dName.exists()) {
System.err.println("The parent directory given should point to an existing directory...");
setStopAll();
return;
}
while (counter < N_TIMES) {
ZipFile zipFile = getMyZipFile(dName);
if (zipFile == null) {
System.err.println("No zip file entry for the Thread-" + myNumber);
break;
}
try {
Enumeration <? extends ZipEntry> zipEntries = zipFile.entries();
fCount = 0;
ZipEntry ze = null;
while (zipEntries.hasMoreElements()) {
ze = zipEntries.nextElement();
if (ze.isDirectory()) continue; // if it is a directory go to next entry
InputStream is = zipFile.getInputStream(ze);
fCount++;
int readCount = 0;
try {
while(is.read((new byte[50])) != -1 && readCount != 200) readCount++;
System.out.println("Successfully Read " + zipFile.toString());
//is.close();
} catch (IOException e) {
e.printStackTrace();
}
if (fCount == N_FILES) break; // read maximum of N_FILES
}
if (stopAll) break;
} catch (Exception e) {
e.printStackTrace();
} finally {
counter++;
}
}
}
public void run () {
try {
doStuff();
} catch (IOException e) {
e.printStackTrace();
setStopAll();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main (String[] args) throws Exception {
final int MAX_THREADS = 500;
final int MAX_HOLDING_THREADS = 5;
int loopCount = 0;
Thread mainThread = Thread.currentThread();
for (int m=0; ; m++) {
Thread t[] = new Thread[MAX_HOLDING_THREADS];
for (int n=0; n<t.length; n++) {
t[n] = new Thread(new ArchiveFileTest());
t[n].start();
if ((m+1)*(n+1)==MAX_THREADS) {
System.out.println("\n" + MAX_THREADS + " reached... \nMain Sleeping for some mins...");
loopCount++;
try {
t[n].join();
System.out.println("\nMain is back... (" + loopCount + ")");
} catch (InterruptedException e) {
e.printStackTrace();
setStopAll();
}
m = 0;
}
}
}
}
}
import java.io.*;
导入java.util.Enumeration;
导入java.util.jar.*;
导入java.util.zip.ZipEntry;
导入java.util.zip.ZipFile;
导入java.util.zip.ZipException;
导入java.io.FilenameFilter;
公共类ArchiveFileTest实现可运行{
私有静态布尔stopAll=false;
私有静态int threadNumber=0;
私有整数myNumber=0;
公共ArchiveFileTest(){
myNumber=螺纹编号;
threadNumber++;
}
公共静态布尔setTopAll(){
返回setStopAll(true);
}
公共静态布尔setTopAll(布尔b){
stopAll=b;
返回停止球;
}
公共静态字符串[]列表文件(文件parentDir、最终字符串ext1、最终字符串ext2、最终字符串ext3、最终字符串ext4){
字符串allFiles[]=parentDir.list(新文件名筛选器(){
公共布尔接受(文件pDir,字符串fName){
如果(fName.endsWith(“.”+ext1)| fName.endsWith(“.”+ext2)| fName.endsWith(“.”+ext3)| fName.endsWith(“.”+ext4))返回true;
否则返回false;
}
});
对于(int i=0;i
在启动线程的类中,为正在运行的线程设置一个volatile
计数器
在线程构造函数中,传递对启动类的引用
有一个同步方法,让线程通知启动类它们已经完成
实例化并启动线程后,等待计数器变为0
while(getRunningThreads() > 0) // getRunningThreads must be synchronized too
Thread.sleep(500); // Check every half second.
如果停止意味着终止,那么当所有线程(非守护进程特例)完成时,应用程序将停止。我认为应用程序永远不会停止。在主方法中有一个无限循环:
for (int m=0; ; m++) {
....
}
请注意,在主体内部设置m=0
不会打破循环,因此我认为即使没有文件,也不会结束。然后,它会连续读取目录中的所有zip/jar/war/rar文件(基于旋转计数器选择文件myNumber
不是很容易维护),但不会退出循环
若您的需求是使用多个线程读取ZIP文件,那个么我将采用另一种方式
创建一组要查看的文件
创建一个可创建5个线程的固定池
迭代文件集并创建一个新的Runnable
,该方法执行Zip提取(尽管我不太清楚为什么读取Zip条目的前10000字节,然后不执行任何操作),并调用execute
方法。该方法将使用线程池一次处理5个文件
提交所有可运行程序后,使用shutdown
方法,等待所有提交的任务完成,然后关闭线程池
如果没有完整的代码,几乎不可能知道代码在做什么(例如,setStopAll()
未定义)我们只能猜测线程是如何创建的,或者目录中有多少个文件。注意:除非设置了stopAll标志,否则每个线程将读取同一个文件15次。我已经用完整的代码更新了这个问题。一个小的OT注释。从设置器中删除boolean作为返回类型,将它们改为return void,因为您不使用return v值和标准是无效的。但这不能保证所有存档文件都已被读取。我想要实现的是在所有文件都已被读取时停止。我只浏览了一下您的代码,但从概念上讲,您不应该使用任何停止方法,布尔值或其他方法来停止您的程序,它应该自行停止,可能已经停止了?什么时候所有文件都已读取。不,它不会停止。我尝试只读取文件夹中的一个文件,但它一直在读取。我必须按住Ctrl+C组合键才能停止它。另外,不要忘记将计数器字段设置为volatile
最好将计数器设置为AtomicInteger,否则,它的值将无法预测。