Java线程池解析

why thread pool

使用线程池的两个理由:

  • 创建一个新线程的代价昂贵,因为它涉及到与操作系统交互。如果程序需要创建大量的生命周期短的线程,就应该使用 线程池 。一个线程池包含多个准备运行的线程。将Runnable对象提交给线程池,线程池中的一个线程就会调用run方法。当run方法运行完成而退出时,该调用线程并不会死亡,而是在线程池中等待服务下一个请求。
  • 使用线程池的另一个理由是为了减少并发线程数目。创建大量的线程会降低虚拟机的性能,甚至崩溃。如果某个算法会创建大量的线程,应该使用线程数“固定的”线程池来限制并发线程总数目。

what is thread pool

Executor类有多个静态工厂方法来创建线程池,如下表:
方法           方法描述
newCachedTreadPool  必要时创建新线程;空闲线程会被保留60秒
newFixedThreadPool  线程池中线程数目是固定的;空闲线程一直被保留
newSingleThreadExecutor  该池只有一个线程,顺序执行提交的任务

newScheduledThreadPool  用于预定执行而构建的固定线程池,替代java.util.Timer
newSingleThreadScheduledThreadPool  用于预定执行而构建的单线程池

上表中的前三个方法返回值是一个实现了ExecutorService接口的ThreadPoolExecutor类的对象。
可以用以下方法之一来提交Runnable对象或者Callable对象给ExecutorService:
返回值类型  方法
Future<?> submit(Runnable task)
Future< T > submit(Runnable task, T result)
Future< T > submit(Callable task)
线程池会在方便的时候尽早的运行提交的任务。调用submit时,会返回一个Future对象用来查询任务的该任务的状态。
当使用线程池完成任务以后,调用shutdown方法。该方法启动该池的关闭序列。调用shutdown之后的线程池不再接受新的任务。当所有任务完成之后,线程池中所有线程死亡。
另一种关闭方法是shutdownNow,调用该方法后线程池将取消所有尚未开始所有任务并试图中断正在运行的线程。

how to use thread pool

综述,使用连接池(connection pool)需要做的步骤:

  • 调用Executor类的静态方法newCachedThreadPool或者静态方法newFixedThreadPool。
  • 调用submit方法提交Runnable对象或者是Callable对象。
  • 为了能够取消一个任务或提交Callable对象,那就要保存好返回的Future对象。
  • 当你不会再提交任何任务时,调用shutdown方法。
    看个实际的例子吧:
/* * ThreadPoolTest.java * 下列代码是在给定的路径下找出给定的关键字出现的次数 */
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;

public class ThreadPoolTest {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("Enter base directory:");
        String directory = in.nextLine();
        System.out.print("Enter keyword:");
        String keyword = in.nextLine();

        ExecutorService pool = Executors.newCachedThreadPool();
        MatchCounter counter = new MatchCounter(new File(directory), keyword, pool);
        Future<Integer> result = pool.submit(counter);

        try {
            System.out.println(result.get() + "matching files.");
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        pool.shutdown();

        int largestPoolSize = ((ThreadPoolExecutor) pool).getLargestPoolSize();
        System.out.println("largest pool size=" + largestPoolSize);
    }

}

class MatchCounter implements Callable<Integer>{
    private File directory; 
    private String keyword; 
    private ExecutorService pool;   
    private int count;

    public MatchCounter(File directory, String keyword, ExecutorService pool) {
        this.directory = directory;
        this.keyword = keyword;
        this.pool = pool;
    }

    public Integer call(){
        count = 0;
        try {
            File files[] = directory.listFiles();
            ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>();

            for (File file : files) {
                if (file.isDirectory()) {
                    MatchCounter counter = new MatchCounter(file, keyword, pool);
                    Future<Integer> result = pool.submit(counter);
                    results.add(result);
                }else {
                    if (search(file))
                        count++;                
                }
            }

            for (Future<Integer> result : results) {
                try {
                    count += result.get();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
        } catch (InterruptedException e) {

        }

        return count;
    }

    /** * 在一个文件中查找给定的单词 */
    public boolean search(File file){
        try {
            Scanner in = new Scanner(new FileInputStream(file));
            boolean found = false;
            while(!found && in.hasNextLine()){
                String line = in.nextLine();
                if (line.contains(keyword)) {
                    found = true;
                }
            }
            in.close();
            return found;
        } catch (IOException e) {
            return false;
        }
    }
}

你可能感兴趣的:(java,线程,线程池)