以往我们实现多线程的方式莫非继承Thread类、或者实现Runnable方法。这种实现的方式过于复杂,没有很深的理解很难掌握。其中的成本是较高的;
无意中看到有使用Future 实现多线程的案例;便进行简单研究并记录下来;
本文的案例场景如下:D盘有200个文件,希望以多线程的方式快速读取并进行分析数据;
首先思考一个问题:什么地方需要多线程处理?
多线程的处理好处就是 不等待 主线程继续执行其他方法;
那么读取文件最为耗时的,所以我们需要将读取文件这个步骤抽取出来 使用多线程方式实现;
那么首先写实现Callable接口的类FileCallable
主要功能:1、实现主线程给子线程进行参数传递
2、实现读取文件功能
3、读取文件内容并封装成ArrayList<databaen> ;
class FileCallable implements Callable< ArrayList<databaen>>{ private String Filename; private String filepath; FileCallable(){}; public FileCallable(String filepath) { this.filepath = filepath; } ArrayList<databaen> datab = new ArrayList<databaen>(); @Override public ArrayList<databaen> call() throws Exception { datab = new ArrayList<databaen>(); File file = new File(filepath); List<String> list = FileUtils.readLines(file, "utf-8"); int size = list.size() - 13; for (int i = 13; i < list.size(); i++) { String al = list.get(i); if (al.indexOf("#") > -1) { size--; continue; } else if (al.indexOf("2018") == 0) { getstrsz(al); } else { continue; } } list = null; return datab; } }
那么干活的人已经有了FileCallable 、下面需要给干活的人造点房子(ExecutorService )让他们好好的干活了,
并且让他们把干活的结果放进我们的仓库(List<Future> )中;
详解源码:ExecutorService ExecutorService= Executors.newFixedThreadPool(5);
为我们的读取的文件的线程创建一个5个线程池;
List<Future> list = new ArrayList<Future>(); 为我们的每一个线程创建一个Future对象来接受劳动果实;
FileCallable FileCallable = new FileCallable(string,FileFactoryReadimp.getfilename(string));
//实例化我的工人将程序必要的参数传递给工人(告诉他文件名称路径是什么)
Future<ArrayList<databaen>> submit = ExecutorService.submit(FileCallable);
//将工人程序提交到线程池中并返回一个 Future<ArrayList<databaen>> 也就是执行的结果
list.add(submit);
//将执行的结果加入list 仓库中后期只要遍历list就能获取所有的劳动果实;
public static void main(String[] args) throws InterruptedException, ExecutionException { FileFactoryReadimp FileFactoryReadimp = new FileFactoryReadimp(); //获取文件列表 String path = "D://bridgetestdemo";// 定义文件路径 ArrayList<String> filelist = FileFactoryReadimp.getfilenames(path); ExecutorService ExecutorService= Executors.newFixedThreadPool(5); List<Future> list = new ArrayList<Future>(); for (int i = 0; i < filelist.size(); i++) { String string = filelist.get(i).toString(); System.out.println(string); FileCallable FileCallable = new FileCallable(string,FileFactoryReadimp.getfilename(string)); Future<ArrayList<databaen>> submit = ExecutorService.submit(FileCallable); list.add(submit); } ExecutorService.shutdown(); for (Future future : list) { ArrayList<databaen> x = (ArrayList<databaen>) future.get(); for (int i = 0; i < x.size(); i++) { databaen databaen = x.get(i); System.out.println(databaen.toString()); } x.clear(); } } }
3个线程读取 -------------- Mon Jun 11 14:45:35 CST 2018 Mon Jun 11 14:47:11 CST 2018 5个线程读取 ---------------------------- Mon Jun 11 14:48:13 CST 2018 Mon Jun 11 14:49:38 CST 2018 6个线程读取 ---------------------------- Mon Jun 11 14:55:41 CST 2018 Mon Jun 11 14:57:12 CST 2018
结果也是比较喜人的;2G的文件读取只需要3分钟左右就完成了
之前单线程读取大约需要20分钟;