(之前梁勇的两本书已经有选择地看完了,之后的时间我大概会着重于线程同步和JVM虚拟机这两大块,所以之后的博客估计都是这两方面的了,偶尔可能会写些刷算法题的博客了)
监控线程用于检测每一个线程的状态,以用于每一个线程结束后的统计。
如下面这个统计电脑的相关文件数据项目
先上完整代码
public class CountFile extends Thread{
private String rootDirName;
private int realFileCount = 0;
private int dirCount = 0;
private int lengthCount = 0;
private boolean finished = false;
public CountFile(String root) {
this.rootDirName = root;
}
public boolean isFinished() {
return finished;
}
public String getResult() {
StringBuffer stb = new StringBuffer();
stb.append(rootDirName + "盘统计结果如下: \r\n" );
stb.append(" 文件数量 " + realFileCount);
stb.append(" 目录数量 " + dirCount);
stb.append(" 文件总长度(K): " + lengthCount + "\n");
stb.append(" ************************* \n");
return stb.toString();
}
public void run() {
long start = System.currentTimeMillis();
lengthCount = countProcess(this.rootDirName);
long timeCost = System.currentTimeMillis() - start;
finished = true;
}
private int countProcess(String dir) {
int count = 0;
File dirFile = new File(dir);
if(!dirFile.exists())
{
return count;
}
File[] subFile = dirFile.listFiles();
if(subFile == null) {
return count;
}
for(int i = 0; i < subFile.length; i ++) {
if(subFile[i].isDirectory()) {
dirCount++;
count += countProcess(subFile[i].getAbsolutePath());
}
if(subFile[i].isFile()) {
realFileCount ++;
count += subFile[i].length();
}
}
return count;
}
}
public class MainCount implements Runnable{
private static List<CountFile> countList = new ArrayList<>();
public void run() {
boolean flag = true;
String result = " ";
while(flag) {
Iterator<CountFile> it = countList.iterator();
while(it.hasNext()) {
CountFile cf = it.next();
if(cf.isFinished()) {
result += cf.getResult();
countList.remove(cf);
}
}
if(countList.isEmpty()) {
flag = false;
}
}
try {
Thread.sleep(3000);
}catch(Exception ef) {}
System.out.println("并行统计结果如下:");
System.out.println(result);
}
public static void main(String[] args) {
File[] dirF = File.listRoots();
for(int i = 0; i < dirF.length; i ++) {
CountFile cf = new CountFile(dirF[i].getAbsolutePath());
cf.start();
countList.add(cf);
}
System.out.println(dirF.length + "个统计线程对象已启动。。");
new Thread(new MainCount()).start();
System.out.println("监视线程已启动。。。");
}
}
这其中起到监测线程作用的是这段代码
public void run() {
boolean flag = true;
String result = " ";
while(flag) {
Iterator<CountFile> it = countList.iterator();
while(it.hasNext()) {
CountFile cf = it.next();
if(cf.isFinished()) {
result += cf.getResult();
countList.remove(cf);
}
}
if(countList.isEmpty()) {
flag = false;
}
}
try {
Thread.sleep(3000);
}catch(Exception ef) {}
System.out.println("并行统计结果如下:");
System.out.println(result);
}
这段代码每隔3s运行一次,只有当所有的之前文件检测的线程都结束了,这个ArrayList才会变为空,最后结束上面这段线程。
按逻辑来说这段代码没有问题,但是实际运行会报 java.util.ConcurrentModificationException的错误。
如下所示
即modCount和expectedModCount的值不一致,造成的原因就是在迭代器遍历过程中你对ArrayList中的数据进行了删除或着增加。next()方法不允许此种行为的存在。
因此,我们必须修改代码,要么选择放弃使用迭代器,或者使用迭代器的remove()方法来使
modCount和expectedModCount的值一致,很显然使用第二个方法,我们就无法实现监测作用了。
因此,我选择放弃迭代器的遍历方法改用循环
int i = 0;
while(flag) {
while(i < countList.size()) {
CountFile cf = countList.get(i);
if(cf.isFinished()) {
result += cf.getResult();
countList.remove(cf);
System.out.print(result);
i = 0;
}
i ++;
}
i = 0;
if(countList.isEmpty()) {
System.out.println("检测结束");
flag = false;
}
}
C盘似乎处于一种无法读取的状态。。导致该监测线程的线程处于一个死循环中出不来。。这个bug我之后再想想看怎么处理。