多线程间通信---监视线程

多线程间通信---监视线程:

 一、多线程间通信---监视线程:

 用自己的话来说,就是线程间的通信,一个线程执行,同时用另一个线程来监视目标线程的运行状态.

 

 二、以统计文件为例:

  1.统计文件的线程类:

package 监控线程;

import java.io.File;

/**
 * 统计某一个磁盘的相关文件数据
 * @author Administrator
 *
 */
public class CountFile extends Thread {

	private String rootDirName;//操作的根目录的名称
	private int dirCount=0;//目录数量
	private int realFileCount=0;//文件数量
	private int lengthCount=0;//文件长度
	private boolean finished =false;//是否运行结束
	
	//传入根目录
	public CountFile(String root){
		this.rootDirName = root;	
	}
	
	//线程进行计算:
	@Override
	public void run() {
		// TODO Auto-generated method stub
		//super.run();
		long start=System.currentTimeMillis();
		//System.out.println(start);
		lengthCount=countProcess(this.rootDirName);
		long timeCost=System.currentTimeMillis()-start;
		//System.out.println(timeCost);
		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();
				
			}			
		}
		
		//System.out.println("count数量:"+count);
		return count;
	}
	
	//线程是否结束
	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("文件总长度(单位:字节):"+lengthCount);
	 
	 return stb.toString();
		
	}
	
}

 

 2.监视线程类:

package 监控线程;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 监控线程通讯模型:
 * 1.启动任务线程
 * 2.对任务线程进行监视
 * @author Administrator
 *
 */
public class MainCount implements Runnable {

	//保存统计线程对象的队列
	private static List<CountFile> countList = new ArrayList();
	
	
	public static void main(String[] args) {
		File[] rootFiles=File.listRoots();
		
		for (int i = 0; i < rootFiles.length; i++) {
			CountFile cb = new CountFile(rootFiles[i].getAbsolutePath());
			cb.start();
			countList.add(cb);//将每个统计线程对象放入要监控的集合中
		}
		
		System.out.println(rootFiles.length+"个统计线程已经启动");
		
		
		//启动监视线程
		new Thread(new MainCount()).start();
		System.out.println("监视线程已经启动");
	}
	
	
	//监控线程每隔3秒钟检测统计线程集合,看是否有
	//完成统计的,如有完成,将其从集合中移除
	@Override
	public void run() {
		// TODO Auto-generated method stub
		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()+"\r\n";//取得统计结果;
			//countList.remove(cf);//移除已经运行完毕的线程
			it.remove();
		}
		
	}
	
	//当统计线程队列为空时,说明所有的任务已执行完毕,本监视线程也要退出
	if(countList.isEmpty()){
		
		flag=false;//让统计线程结束
		
	}
	
	try{
		Thread.sleep(1000);
	}catch(Exception e){
		
	}
		
	}
	System.out.println("并行统计结果如下:");
	System.out.println(result);
	}
}

 

 三、运行结果:

 

1.第1次运行结果:

 

多线程间通信---监视线程_第1张图片
 

2.第2次运行结果:


多线程间通信---监视线程_第2张图片
 

 四、我的盘:

多线程间通信---监视线程_第3张图片
 

 五、运行结果分析:

 通过我的盘,和两次的运行结果综合对比,发现两次的运行结果不一样的

,而且还出现负值

 

 六、查看资料:

File类的length方法.


 多线程间通信---监视线程_第4张图片
 

通过看API发现:

    1.文件夹也是有长度的

    2.当文件是文件夹时,返回值是随机的,这个也就是可以解释为什么是负值的,和长度大小不一样的

 

 

七、补充:

   在移除已经运行完毕的线程时,使用List.remove(i)的方法会出现:ConcurrentModificationException异常

ConcurrentModificationException异常:


多线程间通信---监视线程_第5张图片
 

 原因是List里面的线程也在修改Collection.具体参见:

   http://www.2cto.com/kf/201403/286536.html

 

八、总结:

 经过这个,了解到了线程通信之监视线程,又给自己补课了

 

你可能感兴趣的:(线程间通信,监视线程)