//参考oreilly net work programming
对于大多数的程序,线程具有自己的开销,启动线程和线程退出后的清理工作要耗费虚拟机相当惊人的工作 量,特别是一个程序生成了上千个线程的情况对于中小容量的网络服务器来说都是经常发生的。即使线程能够很快结束,她也会载入无用的编译模块或虚拟几的其他部分。
通过重新使用线程,即可以提高资源的利用率,又可以避免过多的线程浪费资源。一旦线程退出,就不可以再次启动该线程,但是可以设计线程,使线程完成一个任务后并不退出,可以将需要完成的所有任务放置在一个队列中或其他数据结构中,并让每个线程完成上一个任务后从队列里取得下一个任务。
实现线程库的最简单的方法是首次建库的时候使用固定数目的线程集合,当库为空时,每个线程在库上等待。当把任务加进库时,则通知所有的等带线程。当一个线程完成了分配给它的任务时,该线程返回库并取得新任务,如果没有新任务,则该线程等待,知道一个新的任务加入到库中。
举例:
利用GZipOutputStream将当前目录下的每一个文件压缩成gzip格式。
GZipThread类
import java.util.*;
import java.util.List;
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.util.zip.GZIPOutputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
/**
该类继承thread 用来压缩文件
他从一个collection中取出任务
直到所有任务都完成了
*/
public class GZipThread
extends Thread {
/**
* 从pool中取出任务;
*/
private List pool;
/**
* 统计已经压缩多少文件了
*/
private static int filesCompressed = 0;
public GZipThread(List pool) {
this.pool = pool;
}
/**
* 该方法必须同步,有可能不同的线程同时fileCompressed++
* 每压缩一次文件 调用一次这个方法
*/
private static synchronized void incrementFilesCompressed() {
filesCompressed++;
}
public void run() {
while (filesCompressed != GZipAllFiles.getNumberOfFilesToBeCompressed()) {
File input = null;
synchronized (pool) {
/**
* 当collection中没有任务了时有3种情况
* ●所有任务已经完成了
* ●程序启动时collection为空
* ●并非所有的文件都加进了collection中,
* 但collection中加入的任务都已经完成了
*/
while (pool.isEmpty()) {
if (filesCompressed == GZipAllFiles.getNumberOfFilesToBeCompressed()) {
// 所有任务都已经完成了
return;
}
try {
pool.wait(); //线程在该对象上等待
}
catch (InterruptedException ex) {
}
}
input = (File) pool.remove(pool.size() - 1); //此时collection中已经不为空了。
//取得一个新的任务
}
if (!input.getName().endsWith(".gz")) { //不要压缩已经压缩的文件
try {
InputStream in = new FileInputStream(input);
in = new BufferedInputStream(in);
File outPut = new File(input.getParent(), input.getName() + ".gz");
if (!outPut.exists()) {//文压缩件不存在,开始压缩
OutputStream out = new FileOutputStream(outPut);
out = new GZIPOutputStream(out);
out = new BufferedOutputStream(out);
int b;
while ( (b = in.read()) != -1) {
out.write(b);
}
out.flush();
out.close();
incrementFilesCompressed();
in.close();
}//完成压缩过程
}
catch (IOException e) {
}
}//结束if
}//结束while,此时所有任务已经完成了
}//结束run方法
}
GZipAllFiles类
import java.util.Vector;
import java.io.File;
public class GZipAllFiles {
public static void main(String[] args) {
/**
* 所有任务放在vector中
*/
Vector pool=new Vector();
/**
* 设定线程组的数量为四,用这四个线程从vector中取出任务并运行
*/
GZipThread[] threads=new GZipThread[THREAD_COUNT];
for (int i = 0; i <threads .length; i++) {
threads[i]=new GZipThread(pool);
threads[i].start();
}
int totalFiles=0;
for (int i = 0; i < args.length; i++) {
File f=new File(args[i]);
if(f.exists())
{
if(f.isDirectory())
{
File[] files=f.listFiles();
for (int j= 0; j < files.length;j++) {
if(!files[j].isDirectory())
{
totalFiles++;
synchronized(pool)
{
pool.add(files[i]);
pool.notifyAll();//激活在pool对象上等待的所有线程
}
}
}
}
else
{
totalFiles++;
synchronized(pool)
{
pool.add(0,f);
pool.notifyAll();
}
}
}//end if block
}//end for block
/**
* 得到所有的要压缩的文件数目
*/
filesToBeCompressed=totalFiles;
/**
* 确定每个线程知道,没有文件要加入库了
*/
for (int i = 0; i < threads.length; i++) {
threads[i].interrupt();
}
}
public static int getNumberOfFilesToBeCompressed()
{
return filesToBeCompressed;
}
public final static int THREAD_COUNT = 4;
private static int filesToBeCompressed = -1;
}