自己的线程池

    技术2022-05-19  23

    线程池我们都听说过,但它具体是如何工作的好像并不清楚。且看下面的分析。

    当一个任务可由4个线程完成时,如果再生成更多的线程则会降低cpu利用率,那么我们只用这四个线程就行了。 但一个线程当它的任务完成时,它就会die,这样我们就不能再利用了。我们有方法让它不die,并把这4个线程放到一个数组(其它数据结构也行)中来循环利用它们,这个数组就是一个 thread pool 了! 真正实现时还要结合这个任务(task)本身以及线程间的通信。 下面是一个例子,代码比较难,慢慢研究。

     

    假设我们想压缩一个目录下所有文件,我们想用几个线程来完成这个任务,每个线程压缩一个文件,当完成压缩后它再去拿一个文件来压缩。首先来看这个线程类:

     

    import java.io.*; import java.util.*; import java.util.zip.*; public class GZipThread extends Thread { private List pool; //pool里面装的是文件 private static int filesCompressed = 0; public GZipThread(List pool) { this.pool = pool; } private static synchronized void incrementFilesCompressed( ) { filesCompressed++; } public void run( ) { while (filesCompressed != GZipAllFiles. getNumberOfFilesToBeCompressed( )) { File input = null; synchronized (pool) { //取文件时要获得锁 while (pool.isEmpty( )) { if (filesCompressed == GZipAllFiles. getNumberOfFilesToBeCompressed( )) { System.out.println("Thread ending"); return; } try { pool.wait( ); //池空则等待 } catch (InterruptedException ex) { } } input = (File) pool.remove(pool.size( )-1); //获得一个文件 incrementFilesCompressed( ); } // don't compress an already compressed file 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( )) { // Don't overwrite an existing file 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( ); in.close( ); } } catch (IOException ex) { System.err.println(ex); } } // end if } // end while } // end run } // end ZipThread

     

    主线程类:

     

    import java.io.*; import java.util.*; public class GZipAllFiles { public final static int THREAD_COUNT = 4; private static int filesToBeCompressed = -1; public static void main(String[] args) { Vector pool = new 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( )) { // don't recurse directories totalFiles++; synchronized (pool) { //放文件时pool中时要获得锁 pool.add(0, files[j]); pool.notifyAll( );//有的线程在pool对象上wait着呢,所以要notifyAll,关于wait用法请看其它篇 } } } } else { totalFiles++; synchronized (pool) { pool.add(0, f); pool.notifyAll( ); } } } // end if } // end for filesToBeCompressed = totalFiles; // make sure that any waiting thread knows that no // more files will be added to the pool for (int i = 0; i < threads.length; i++) { threads[i].interrupt( ); //当filesToBeCompressed = totalFiles时表明任务完成,这时wait()的线程要被唤醒,再次循环时while条件不成立而退出 } } public static int getNumberOfFilesToBeCompressed( ) { return filesToBeCompressed; } }

     

    这个文章主要是自己看,不太懂其它同行,原文在“Java Network Programming 3rd” 第五章 Threads 中的 5.6 Thread pools.

     


    最新回复(0)