JAVA线程池

简介: 在Java 5.0之前启动一个任务是通过调用Thread类的start()方法来实现的,任务的提于交和执行是同时进行的,如果你想对任务的执行进行调度或是控制 同时执行的线程数量就需要额外编写代码来完成。

     在Java 5.0之前启动一个任务是通过调用Thread类的start()方法来实现的,任务的提于交和执行是同时进行的,如果你想对任务的执行进行调度或是控制 同时执行的线程数量就需要额外编写代码来完成。5.0里提供了一个新的任务执行架构使你可以轻松地调度和控制任务的执行,并且可以建立一个类似数据库连接 池的线程池来执行任务。这个架构主要有三个接口和其相应的具体类组成。这三个接口是Executor, ExecutorService、ScheduledExecutorService,让我们先用一个图来显示它们的关系:

   

图的左侧是接口,图的右侧是这些接口的具体类。注意Executor是没有直接具体实现的。

 

Executor接口:是用来执行Runnable任务的,它只定义一个方法:

 

  • execute(Runnable command):执行Ruannable类型的任务

 

ExecutorService接口:ExecutorService继承了Executor的方法,并提供了执行Callable任务和中止任务执行的服务,其定义的方法主要有:

 

  • submit(task):可用来提交Callable或Runnable任务,并返回代表此任务的Future对象
  • invokeAll(collection of tasks):批处理任务集合,并返回一个代表这些任务的Future对象集合
  • shutdown():在完成已提交的任务后关闭服务,不再接受新任务
  • shutdownNow():停止所有正在执行的任务并关闭服务。
  • isTerminated():测试是否所有任务都执行完毕了。
  • isShutdown():测试是否该ExecutorService已被关闭

 

ScheduledExecutorService接口在ExecutorService的基础上,ScheduledExecutorService提供了按时间安排执行任务的功能,它提供的方法主要有:

 

  • schedule(task, initDelay): 安排所提交的Callable或Runnable任务在initDelay指定的时间后执行。
  • scheduleAtFixedRate():安排所提交的Runnable任务按指定的间隔重复执行
  • scheduleWithFixedDelay():安排所提交的Runnable任务在每次执行完后,等待delay所指定的时间后重复执行。

 

 

 

重要的Executors

 

虽然以上提到的接口有其实现的具体类,但为了方便Java 5.0建议使用Executors的工具类来得到Executor接口的具体对象,需要注意的是Executors是一个类,不是Executor的复数 形式。Executors提供了以下一些static的方法:

 

  • callable(Runnable task): 将Runnable的任务转化成Callable的任务
  • newSingleThreadExecutor: 产生一个ExecutorService对象,这个对象只有一个线程可用来执行任务,若任务多于一个,任务将按先后顺序执行。
  • newCachedThreadPool(): 产生一个ExecutorService对象,这个对象带有一个线程池,线程池的大小会根据需要调整,线程执行完任务后返回线程池,供执行下一次任务使用。
  • newFixedThreadPool(int poolSize):产生一个ExecutorService对象,这个对象带有一个大小为poolSize的线程池,若任务数量大于poolSize,任务会被放在一个queue里顺序执行。
  • newSingleThreadScheduledExecutor:产生一个ScheduledExecutorService对象,这个对象的线程池大小为1,若任务多于一个,任务将按先后顺序执行。
  • newScheduledThreadPool(int poolSize): 产生一个ScheduledExecutorService对象,这个对象的线程池大小为poolSize,若任务数量大于poolSize,任务会在一个queue里等待执行

实例:

 

  1 import java.io.*;
  2 import java.util.*;
  3 import java.util.concurrent.*;
  4 
  5 public class ThreadPoolTest
  6 {
  7    public static void main(String[] args) throws Exception
  8    {
  9       Scanner in = new Scanner(System.in);
 10       System.out.print("Enter base directory (e.g. /usr/local/jdk5.0/src): ");
 11       String directory = in.nextLine();
 12       System.out.print("Enter keyword (e.g. volatile): ");
 13       String keyword = in.nextLine();     
 14 
 15       ExecutorService pool = Executors.newCachedThreadPool();
 16       
 17       MatchCounter counter = new MatchCounter(new File(directory), keyword, pool);           
 18       Future<Integer> result = pool.submit(counter);
 19 
 20       try
 21       {
 22          System.out.println(result.get() + " matching files.");
 23       }
 24       catch (ExecutionException e)
 25       {
 26          e.printStackTrace();
 27       }
 28       catch (InterruptedException e) {}
 29       pool.shutdown();
 30 
 31       int largestPoolSize = ((ThreadPoolExecutor) pool).getLargestPoolSize();
 32       System.out.println("largest pool size=" + largestPoolSize);
 33    }
 34 }
 35 
 36 /**
 37    This task counts the files in a directory and its subdirectories that contain a given keyword.
 38 */
 39 class MatchCounter implements Callable<Integer>
 40 {
 41    /**
 42       Constructs a MatchCounter.
 43       @param directory the directory in which to start the search
 44       @param keyword the keyword to look for
 45       @param pool the thread pool for submitting subtasks
 46    */
 47    public MatchCounter(File directory, String keyword, ExecutorService pool)
 48    {
 49       this.directory = directory;      
 50       this.keyword = keyword;
 51       this.pool = pool;
 52    }
 53 
 54    public Integer call()
 55    {
 56       count = 0;
 57       try
 58       {
 59          File[] files = directory.listFiles();
 60          ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>();
 61 
 62          for (File file : files)      
 63             if (file.isDirectory()) 
 64             {               
 65                MatchCounter counter = new MatchCounter(file, keyword, pool);           
 66                Future<Integer> result = pool.submit(counter);
 67                results.add(result);
 68             }
 69             else 
 70             {
 71                if (search(file)) count++;
 72             }
 73          
 74          for (Future<Integer> result : results)
 75             try
 76             {
 77                count += result.get();
 78             }
 79             catch (ExecutionException e)
 80             {
 81                e.printStackTrace();
 82             }
 83       }
 84       catch (InterruptedException e) {}
 85       return count;
 86    }
 87 
 88    /**
 89       Searches a file for a given keyword.
 90       @param file the file to search
 91       @return true if the keyword is contained in the file
 92    */
 93    public boolean search(File file)
 94    {     
 95       try
 96       {
 97          Scanner in = new Scanner(new FileInputStream(file));
 98          boolean found = false;
 99          while (!found && in.hasNextLine())
100          {
101             String line = in.nextLine();
102             if (line.contains(keyword)) found = true;
103          }
104          in.close();
105          return found;
106       }
107       catch (IOException e)
108       {
109          return false;
110       }
111    }
112 
113    private File directory;
114    private String keyword;
115    private ExecutorService pool;
116    private int count;
117 }

 

 

 

相关文章
|
13天前
|
Java 调度
Java并发编程:深入理解线程池的原理与实践
【4月更文挑战第6天】本文将深入探讨Java并发编程中的重要概念——线程池。我们将从线程池的基本原理入手,逐步解析其工作过程,以及如何在实际开发中合理使用线程池以提高程序性能。同时,我们还将关注线程池的一些高级特性,如自定义线程工厂、拒绝策略等,以帮助读者更好地掌握线程池的使用技巧。
|
21天前
|
Java 程序员
java线程池讲解面试
java线程池讲解面试
38 1
|
15天前
|
Java
深入理解Java并发编程:线程池的应用与优化
【4月更文挑战第3天】 在Java并发编程中,线程池是一种重要的资源管理工具,它能有效地控制和管理线程的数量,提高系统性能。本文将深入探讨Java线程池的工作原理、应用场景以及优化策略,帮助读者更好地理解和应用线程池。
|
11天前
|
Java
Java 并发编程:深入理解线程池
【4月更文挑战第8天】本文将深入探讨 Java 中的线程池技术,包括其工作原理、优势以及如何使用。线程池是 Java 并发编程的重要工具,它可以有效地管理和控制线程的执行,提高系统性能。通过本文的学习,读者将对线程池有更深入的理解,并能在实际开发中灵活运用。
|
30天前
|
监控 Java
Java并发编程中的线程池优化技巧
在Java并发编程中,线程池扮演着至关重要的角色。本文将深入探讨如何优化Java线程池,从线程池的创建与配置、任务队列的选择、拒绝策略的制定、线程池状态的监控等多个方面进行详细阐述。通过本文的阅读,您将了解到如何合理地利用线程池,提高系统的并发性能,从而更好地应对各种并发场景。
|
11天前
|
Java
Java并发编程:深入理解线程池
【4月更文挑战第7天】在现代软件开发中,多线程编程已经成为一种不可或缺的技术。为了提高程序性能和资源利用率,Java提供了线程池这一强大工具。本文将深入探讨Java线程池的原理、使用方法以及如何根据实际需求定制线程池,帮助读者更好地理解和应用线程池技术。
15 0
|
2天前
|
存储 缓存 监控
Java线程池
Java线程池
14 1
|
28天前
|
Java
Java中线程池的深入理解与实践
【2月更文挑战第30天】本文将详细探讨Java中的线程池,包括其基本原理、应用场景以及如何在实际项目中使用。我们将通过实例代码来演示如何创建和管理线程池,以及如何优化线程池的性能。
|
29天前
|
Java
Java并发编程:线程池的深入理解与实践
【2月更文挑战第29天】在Java并发编程中,线程池是一种重要的技术手段,它可以有效地管理和控制线程,提高系统性能。本文将深入探讨线程池的原理,解析其关键参数,并通过实例演示如何在实际开发中合理使用线程池。
|
30天前
|
Java 开发者
深入理解Java并发编程:线程池的应用与优化
【2月更文挑战第29天】本文将深入探讨Java并发编程中的重要概念——线程池。我们将首先介绍线程池的基本概念和原理,然后详细解析线程池的使用方法和注意事项,最后探讨如何优化线程池的性能。通过本文的学习,你将能够掌握线程池的核心知识,提高你的Java并发编程能力。