Java 多线程,线程池,
1. 创建线程池的方法之三:
//对于每个任务,如果有空闲的线程可用,立即让他执行任务, //没有空闲的线程则创建一个线程。 ExecutorService pool = Executors.newCachedThreadPool(); //固定大小的线程池,任务数 > 空闲线程数,得不到服务的任务置于队列 ExecutorService pool = Executors.newFixedThreadPool; //退化的大小为1的线程池,由一个线程逐个执行提交的任务。 ExecutorService pool = Executors.newSingleThreadPool();
2. 把任务交给线程池:
//返回的对象可以调用isDone(),cancel(),isCancelled Future<?> submit(Runnable task); //get() 返回指定的result对象 Future<T> submit(Runnable task,T result); //返回的对象将在计算结果准备好的时候得到它。 Future<T> submit(Callable<T> task);
3.用完一个线程池的时候,调用shutdown() 启动线程池的关闭序列。被关闭的执行器不再接受新的任务,当任务都结束后,线程池中的线程死亡。
4. 案例:给定一个目录,查找目录中文本文档内容包含指定关键字的文档的数量。
条件:目录、关键字
4.1 任务类(线程类)
/** 线程任务:计算目录中所有包含给定关键字的文件的数量。*/ class MatchCounter implements Callable<Integer> { private File directory; private String keyword; private ExecutorService pool; private int count; /** * Constructs a MatchCounter. * @param directory 给定的目录 * @param keyword 关键字 * @param pool 用来执行任务的线程池 */ public MatchCounter(File directory, String keyword, ExecutorService pool) { this.directory = directory; this.keyword = keyword; this.pool = pool; } @Override public Integer call() { count = 0; try { File[] files = directory.listFiles(); //线程执行结果集合 List<Future<Integer>> results = new ArrayList<>(); for (File file : files) //遍历给定目录中的所有文件 //如果是文件夹 if (file.isDirectory()) { //递归 MatchCounter counter = new MatchCounter(file, keyword, pool); Future<Integer> result = pool.submit(counter); results.add(result); } //如果是文件,则调用search()方法 看是否包含关键字。 else { if (search(file)) count++; } for (Future<Integer> result : results) try { int a = result.get(); count += result.get(); } catch (ExecutionException e) { e.printStackTrace(); } } catch (InterruptedException e) { } return count; } /** * Searches a file for a given keyword. * @param file the file to search * @return true if the keyword is contained in the file */ public boolean search(File file) { try { try (Scanner in = new Scanner(file, "UTF-8")) { boolean found = false; while (!found && in.hasNextLine()) { String line = in.nextLine(); if (line.contains(keyword)) found = true; } return found; } } catch (IOException e) { return false; } } }
4.2 主程序
public class ThreadPoolTest { public static void main(String[] args) throws Exception { try (Scanner in = new Scanner(System.in)) { System.out.print("请输入要查找的目录:"); String directory = in.nextLine(); System.out.print("请输入要查找的关键字:"); 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() + " 匹配的文件"); } catch (ExecutionException e) { e.printStackTrace(); } catch (InterruptedException e) { } pool.shutdown(); int largestPoolSize = ((ThreadPoolExecutor) pool).getLargestPoolSize(); System.out.println("线程池最大数量 =" + largestPoolSize); } } }
4.3 运行结果: