打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
线程池 —— 使用介绍
userphoto

2017.03.04

关注
());}```运行实例:```javaExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);for (int i = 1; i <= 10;="" i++)="" {="" final="" int="" index="i;" fixedthreadpool.execute(new="" runnable()="" {="" @override="" public="" void="" run()="" {="" string="" threadname="Thread.currentThread().getName();" system.out.println('thread:="" '="" +="" threadname="" +="" ',="" running="" task'="" +="" index);="" try="" {="" thread.sleep(3000);="" }="" catch="" (interruptedexception="" e)="" {="" e.printstacktrace();="" }="" }="" });}```运行结果:```02-24="" 08:15:20="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task102-24="" 08:15:20="" i/system.out:="" thread:="" pool-1-thread-2,="" running="" task202-24="" 08:15:20="" i/system.out:="" thread:="" pool-1-thread-3,="" running="" task302-24="" 08:15:23="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task402-24="" 08:15:23="" i/system.out:="" thread:="" pool-1-thread-2,="" running="" task502-24="" 08:15:23="" i/system.out:="" thread:="" pool-1-thread-3,="" running="" task602-24="" 08:15:26="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task702-24="" 08:15:26="" i/system.out:="" thread:="" pool-1-thread-2,="" running="" task802-24="" 08:15:26="" i/system.out:="" thread:="" pool-1-thread-3,="" running="" task902-24="" 08:15:29="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task10```观察线程名发现一共只创建了="" 3="" 个线程处理任务,当所有线程都处于运行状态时,再提交的任务则会进入等待,3="" 个线程处理完之前任务后会被等待队列中的任务复用,所以观察时间发现,每次都是="" 3="" 个任务同时运行,间隔="" 3="" 秒后再运行后面="" 3="" 个任务,任务执行的顺序即提交的顺序。###="" 2.="" 缓存型线程池="" `newcachedthreadpool`创建一个可以根据实际情况调整线程数量的线程池。线程池中的线程数量不确定,当需要时会创建新的线程,当有线程空闲时复用空闲线程。通常对执行大量短暂异步任务的程序,可以提升其效率。当然,线程池中的线程并不会越来越多,每个线程都有一个参数用来设置保持活动的时间,一旦线程空闲时间超过了该时间,则立即销毁该线程,默认的保持活动时间为="" 60="" 秒,我们可以在其定义中看到这个默认参数。定义:```javapublic="" static="" executorservice="" newcachedthreadpool()="" {="" return="" new="" threadpoolexecutor(0,="" integer.max_value,="" 60l,="" timeunit.seconds,="" new="">());}```运行实例:```javaExecutorService cachedThreadPool = Executors.newCachedThreadPool();for (int i = 1; i <= 10;="" i++)="" {="" try="" {="" thread.sleep(1000);="" }="" catch="" (interruptedexception="" e)="" {="" e.printstacktrace();="" }="" final="" int="" index="i;" cachedthreadpool.execute(new="" runnable()="" {="" @override="" public="" void="" run()="" {="" string="" threadname="Thread.currentThread().getName();" system.out.println('thread:="" '="" +="" threadname="" +="" ',="" running="" task'="" +="" index);="" try="" {="" thread.sleep(index="" *="" 500);="" }="" catch="" (interruptedexception="" e)="" {="" e.printstacktrace();="" }="" }="" });}```运行结果:```02-24="" 08:25:29="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task102-24="" 08:25:30="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task202-24="" 08:25:31="" i/system.out:="" thread:="" pool-1-thread-2,="" running="" task302-24="" 08:25:32="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task402-24="" 08:25:33="" i/system.out:="" thread:="" pool-1-thread-2,="" running="" task502-24="" 08:25:34="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task602-24="" 08:25:35="" i/system.out:="" thread:="" pool-1-thread-3,="" running="" task702-24="" 08:25:36="" i/system.out:="" thread:="" pool-1-thread-2,="" running="" task802-24="" 08:25:37="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task902-24="" 08:25:38="" i/system.out:="" thread:="" pool-1-thread-4,="" running="" task10```我们让任务间隔="" 1="" 秒提交一次,并且每个任务的时间逐渐增长,从结果可以发现,每隔="" 1="" 秒就会有一个任务被执行,刚开始一个线程可以处理过来,但随着任务时间的增长,线程池创建了新的线程来处理那些提交的任务,当有之前的线程处理完后,也会被赋予任务执行。最后一共创建了="" 4="" 个线程。###="" 3.="" 单例线程="" `newsinglethreadexecutor`创建一个只含有一个线程的线程池。每次只能执行一个线程任务,多余的任务会保存到一个任务队列中,当这个线程空闲时,再按照="" fifo="" 的方式顺序执行队列中的任务。定义:```javapublic="" static="" executorservice="" newsinglethreadexecutor(threadfactory="" threadfactory)="" {="" return="" new="" finalizabledelegatedexecutorservice="" (new="" threadpoolexecutor(1,="" 1,="" 0l,="" timeunit.milliseconds,="" new="">(), threadFactory));}```运行实例:```javaExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();for (int i = 1; i <= 10;="" i++)="" {="" final="" int="" index="i;" singlethreadexecutor.execute(new="" runnable()="" {="" @override="" public="" void="" run()="" {="" string="" threadname="Thread.currentThread().getName();" system.out.println('thread:="" '="" +="" threadname="" +="" ',="" running="" task'="" +="" index);="" try="" {="" thread.sleep(1000);="" }="" catch="" (interruptedexception="" e)="" {="" e.printstacktrace();="" }="" }="" });}```运行结果:```02-24="" 09:00:18="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task102-24="" 09:00:19="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task202-24="" 09:00:20="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task302-24="" 09:00:21="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task402-24="" 09:00:22="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task502-24="" 09:00:23="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task602-24="" 09:00:24="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task702-24="" 09:00:25="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task802-24="" 09:00:26="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task902-24="" 09:00:27="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task10```结果显而易见,从始至终只有一个线程在执行,该线程顺序执行已提交的线程。###="" 4.="" 调度型线程池="" `newscheduledthreadpool`创建一个可指定大小的,可以调度线程根据="" schedule="" 延迟执行,或者周期执行的线程池。运行实例:```javasystem.out.println('start="" task');scheduledexecutorservice="" scheduledthreadpool="Executors.newScheduledThreadPool(3);for" (int="" i="1;" i=""><= 10;="" i++)="" {="" final="" int="" index="i;" scheduledthreadpool.schedule(new="" runnable()="" {="" @override="" public="" void="" run()="" {="" string="" threadname="Thread.currentThread().getName();" system.out.println('thread:="" '="" +="" threadname="" +="" ',="" running="" task'="" +="" index);="" try="" {="" thread.sleep(2000);="" }="" catch="" (interruptedexception="" e)="" {="" e.printstacktrace();="" }="" }="" },="" 3,="" timeunit.seconds);}```运行结果:```02-24="" 09:47:45="" i/system.out:="" start="" task02-24="" 09:47:48="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task102-24="" 09:47:48="" i/system.out:="" thread:="" pool-1-thread-2,="" running="" task202-24="" 09:47:48="" i/system.out:="" thread:="" pool-1-thread-3,="" running="" task302-24="" 09:47:50="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task502-24="" 09:47:50="" i/system.out:="" thread:="" pool-1-thread-2,="" running="" task402-24="" 09:47:50="" i/system.out:="" thread:="" pool-1-thread-3,="" running="" task602-24="" 09:47:52="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task702-24="" 09:47:52="" i/system.out:="" thread:="" pool-1-thread-3,="" running="" task802-24="" 09:47:52="" i/system.out:="" thread:="" pool-1-thread-2,="" running="" task902-24="" 09:47:54="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task10```运行情况基本和="" newfixedthreadpool="" 类似,但是在开始运行时,有="" 3="" 秒钟的延迟。###="" 5.="" 调度型单例线程="" `newsinglethreadscheduledexecutor`创建一个只含有一个线程,可以调度线程根据="" schedule="" 延迟执行,或者周期执行的线程池。运行实例:```javasystem.out.println('start="" task');scheduledexecutorservice="" singlethreadscheduledexecutor="Executors.newSingleThreadScheduledExecutor();singleThreadScheduledExecutor.scheduleAtFixedRate(new" runnable()="" {="" @override="" public="" void="" run()="" {="" string="" threadname="Thread.currentThread().getName();" system.out.println('thread:="" '="" +="" threadname="" +="" ',="" running="" task1');="" }},="" 1,="" 2,="" timeunit.seconds);```运行结果:```02-24="" 10:01:36="" i/system.out:="" start="" task02-24="" 10:01:37="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task02-24="" 10:01:39="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task02-24="" 10:01:41="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task02-24="" 10:01:43="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task02-24="" 10:01:45="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task02-24="" 10:01:47="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task02-24="" 10:01:49="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task02-24="" 10:02:51="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task02-24="" 10:02:53="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task02-24="" 10:02:55="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" task```运行情况基本和="" newsinglethreadexecutor="" 类似,但是在开始运行时,有="" 1="" 秒钟的延迟,并且每隔="" 2="" 秒周期性的执行一次任务。##="" 自定义线程池如果仔细观察上面五种线程池的定义就会有所发现,其实线程池的功能不同,和其内部的="" blockingqueue="" 不同有关。如果我们想要实现一些不同功能的自定义线程池,可以从其中的="" blockingqueue="" 着手。比如现在有一种="" blockingqueue="" 的实现类是="" priorityblockingqueue,他可以实现队列按照优先级排序,那我们就可以利用它实现一个按任务的优先级来处理任务的线程池。首先创建一个实现了="" runnable="" 与="" comparable="" 接口的抽象类="" priorityrunnable,用来存放任务。实现了="" comparable="" 接口就可以进行优先级的比较。```javapublic="" abstract="" class="" priorityrunnable="" implements="" runnable,=""> { private int mPriority; public PriorityRunnable(int priority) { if (priority < 0="" )="" {="" throw="" new="" illegalargumentexception();="" }="" mpriority="priority;" }="" @override="" public="" int="" compareto(priorityrunnable="" runnable)="" {="" int="" otherpriority="runnable.getPriority();" if="" (mpriority="">< otherpriority)="" {="" return="" 1;="" }="" else="" if="" (mpriority=""> otherPriority) { return -1; } else { return 0; } } public int getPriority() { return mPriority; }}```接着就可以创建一个基于 PriorityBlockingQueue 实现的线程池,其核心数量定义为 3,方便测试结果。然后创建 10 个优先级依次增加的 PriorityRunnable 任务,提交给线程池执行。```javaExecutorService threadPool = new ThreadPoolExecutor(3, 3, 0L, TimeUnit.SECONDS, new PriorityBlockingQueue());for (int i = 1; i <= 10;="" i++)="" {="" final="" int="" priority="i;" threadpool.execute(new="" priorityrunnable(priority)="" {="" @override="" public="" void="" run()="" {="" string="" name="Thread.currentThread().getName();" system.out.println('thread:="" '="" +="" name="" +="" ',="" running="" prioritytask'="" +="" priority);="" try="" {="" thread.sleep(2000);="" }="" catch="" (interruptedexception="" e)="" {="" e.printstacktrace();="" }="" }="" });}```运行结果:```02-25="" 11:34:45="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" prioritytask102-25="" 11:34:45="" i/system.out:="" thread:="" pool-1-thread-2,="" running="" prioritytask202-25="" 11:34:45="" i/system.out:="" thread:="" pool-1-thread-3,="" running="" prioritytask302-25="" 11:34:47="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" prioritytask1002-25="" 11:34:47="" i/system.out:="" thread:="" pool-1-thread-2,="" running="" prioritytask902-25="" 11:34:47="" i/system.out:="" thread:="" pool-1-thread-3,="" running="" prioritytask802-25="" 11:34:49="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" prioritytask702-25="" 11:34:49="" i/system.out:="" thread:="" pool-1-thread-2,="" running="" prioritytask602-25="" 11:34:49="" i/system.out:="" thread:="" pool-1-thread-3,="" running="" prioritytask502-25="" 11:34:51="" i/system.out:="" thread:="" pool-1-thread-1,="" running="" prioritytask4```可以看到,运行结果和="" newfixedthreadpool="" 非常相似,唯一不同就在于等待任务不是按照="" fifo="" 的方式执行,而是优先级较高的任务先执行。##="" 线程池的优化线程池可以自定义内部线程的数量,定义的数量影响着系统的性能表现,如果定义过大会浪费资源,定义过小线程并发量太低,处理速度也变低了,所以合理的设置线程数量是很重要的。通常需要考虑="" cpu="" 的核心数、内存的大小、并发请求的数量等因素。通常核心线程数量可以设为="" cpu="" 核心数="" +="" 1,最大线程数量可以设为="" cpu="" 核心数="" *="" 2="" +="" 1。获取="" cpu="" 核心数的方法为:```javaruntime.getruntime().availableprocessors();```##="" 线程池的调用方式以下方法都可以调用线程池执行,但是效果不同,可以参考文档或源码了解:*="" `void="" execute(runnable="" command);`*="" `future="" submit(runnable="" task);`*=""> Future submit(Runnable task, T result);`* ` Future submit(Callable task);`* ` T invokeAny(Collection> tasks);`* ` List<>> invokeAll(Collection> tasks)`## 线程池的关闭### `void shutdown();`该方法不再接受新的任务提交,在终止线程池之前,允许执行完以前提交的任务。### `List shutdownNow();`该方法不再接受新的任务提交,并且把任务队列中的任务直接移除,尝试停止正在执行的任务。返回等待的任务列表。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
多核开发入门指南
C#中的队列,Queue类与多线程使用
24个时间管理小技巧
你是一心二用的supertasker吗 ?
storm的总体介绍
线程池学习 多线程JavaSocketDOS编程
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服