Java线程池解析

原创 2015年11月20日 12:46:28

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线程、线程池、xml解析入门

  • 2012年08月17日 12:08
  • 2.3MB
  • 下载

JAVA并发API源码解析:并发数据结构、线程、线程池及其应用

首先介绍Callable这个接口,它仅包含一个方法call,它是类似于Runnable接口,是Future并发设计模式下实际的任务执行单元,它能返回一个对象。我们可以实现它的子类并使用Future对象...

Java线程池的原理与实现

  • 2010年05月14日 17:33
  • 14KB
  • 下载

JAVA线程池的分析和使用

  • 2015年08月26日 10:09
  • 25KB
  • 下载

java的Executors类中创建线程池方法的解析

1,newFixedThreadPool(int nThreads) 创建一个重复利用一定数目线程的线程池。在任何时候,最多只能有nThreads个线程运行。当全部的线程都在运行,如果额外的任务提交...

Java线程池应用

  • 2013年12月10日 23:04
  • 476KB
  • 下载

Java 线程池原理解析(一)

大多数的并发应用程序都是围绕”任务执行”来构造的:任务通常是一些离散的单元。所谓高并发的主要任务就是把应用程序中的工作分解到多个任务当中,并且这些任务是相互独立的:任务不依赖于其他任务的状态。任务之间...

Java线程池.pdf

  • 2008年02月29日 10:04
  • 251KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java线程池解析
举报原因:
原因补充:

(最多只允许输入30个字)