使用线程池优化多线程编程html
认识线程池java
在Java中,全部的对象都是须要经过new操做符来建立的,
若是建立大量短生命周期的对象,将会使得整个程序的性能很是的低下。
这种时候就须要用到了池的技术,好比数据库链接池,线程池等。数据库
在java1.5以后,java自带了线程池,在util包下新增了concurrent包,
这个包主要做用就是介绍java线程和线程池如何使用的。编程
在包java.util.concurrent下的 Executors类中定义了Executor、ExecutorService、ScheduledExecutorService、
ThreadFactoryScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。缓存
此类支持如下各类方法:
a.建立并返回设置有经常使用配置字符串的 ExecutorService 的方法。
b.建立并返回设置有经常使用配置字符串的 ScheduledExecutorService 的方法。
c.建立并返回“包装的”ExecutorService 方法,它经过使特定于实现的方法不可访问来禁用从新配置。
d.建立并返回 ThreadFactory 的方法,它可将新建立的线程设置为已知的状态。
e.建立并返回非闭包形式的 Callable 的方法,这样可将其用于须要 Callable 的执行方法中。
--若是朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3897773.html "谢谢--
首先咱们先来比较一下用线程池建立多个线程和用独立运行的方式建立多个线程的区别,
这里咱们将经过比较两种方法占有内存和花费时间,来讲明线程池的必要性和重要性。多线程
代码实例:闭包
package com.xhj.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 比较独立建立和线程池建立线程的优劣 比较因素--时间和占用内存 * * @author XIEHEJUN * */ public class CompareThreadPool implements Runnable { private int id = 0; @Override public void run() { id++; } public static void main(String[] args) { /** * 独立建立1000个线程 */ { // 获取当前程序运行时对象 Runtime run = Runtime.getRuntime(); // 调用垃圾回收机制,以减小内存偏差 run.gc(); // 获取当前JVM的空闲内存 long freeMemory = run.freeMemory(); // 系统当前时间 long timePro = System.currentTimeMillis(); // 独立建立并执行1000个线程 for (int i = 0; i < 1000; i++) { new Thread(new CompareThreadPool()).start(); } System.out.println("独立建立并执行1000个线程所须要占用的内存大小: " + (freeMemory - run.freeMemory())); System.out.println("独立建立并运行1000个线程须要的时间为: " + (System.currentTimeMillis() - timePro)); } /** * 利用线程池建立1000个线程 */ { // 获取当前程序运行时对象 Runtime run = Runtime.getRuntime(); // 调用垃圾回收机制,以减小内存偏差 run.gc(); // 获取当前JVM的空闲内存 long freeMemory = run.freeMemory(); // 系统当前时间 long timePro = System.currentTimeMillis(); ExecutorService service = Executors.newFixedThreadPool(2); // 线程池建立并执行1000个线程 for (int i = 0; i < 1000; i++) { service.submit(new CompareThreadPool()); } System.out.println("使用线程池建立1000个线程所须要占用的内存大小: " + (freeMemory - run.freeMemory())); // 线程池使用完成,关闭线程池 service.shutdown(); System.out.println("使用线程池建立并运行1000个线程须要的时间为: " + (System.currentTimeMillis() - timePro)); } } }
结果为:ide
结论--为何要用线程池:
经过上面这个例子,咱们知道使用线程池能够大大的提升系统的性能,提升程序任务的执行效率,
节约了系统的内存空间。在线程池中,每个工做线程均可以被重复利用,可执行多个任务,
减小了建立和销毁线程的次数。可以根据系统的承受能力,调整其线程数目,以便使系统达到运行的最佳效果。工具
线程池原理:
一个线程池中有多个处于可运行状态的线程,当向线程池中添加Runnable或Callable接口对象时,
就会有一个线程来执行run()方法或call()方法。若是方法执行完毕,则该线程并不终止,
而是继续在池中处于可运行状态,以运行新的任务。性能
了解线程池(java中建立线程池的几种经常使用静态方法)
在java中,线程池的顶级接口是util.concurrent包下的Executors工具类,在这个类里,定义了不少操做线程池的方法。
其中最经常使用的线程池有:
1.建立单线程的线程池:
newSingleThreadExecutor(),建立一个只有一个线程的线程池,此单线程按照任务的提交顺序执行全部的任务,
若遇到异常中断,线程池则会从新创建一个单线程来替代其完成后续工做。
代码实例:
/** * 建立一个单线程的线程池 * * @return */ public ExecutorService SingleThreadPool() { ExecutorService singlePool = Executors.newSingleThreadExecutor(); return singlePool; }
2.建立一个可缓存的线程池:
newCachedThreadPool(),建立一个不限制大小,且只能的线程池,他会根据任务量的多少来开辟和减小内存空间,
可是线程池中线程的大小依赖于系统的性能或者JVM的容量
代码实例:
/** * 建立一个可缓存线程池 * * @return */ public ExecutorService CachedThreadPool() { ExecutorService cachedPool = Executors.newCachedThreadPool(); return cachedPool; }
3.建立一个大小固定的线程池:
newFixedThreadPool(),建立一个固定大小的线程池,任务提交则创建线程,直到线程大小达到线程池容许最大值,
若某个线程结束,线程池则补充一个新的线程。
代码实例:
/** * 建立一个大小固定的线程池 * * @return */ public ExecutorService FixedThreadPool() { ExecutorService fixedPool = Executors.newFixedThreadPool(2); return fixedPool; }
4.建立一个可定时、周期性执行的线程池
newScheduledThreadPool(),建立一个可定时、周期性执行的线程池,此线程池没有大小限制,
实现周期性任务调度。
代码实例:
ScheduledThreadPoolExecutor scheduledPool = new ScheduledThreadPoolExecutor(1);
为了便于你们理解和对比其不一样之处,下面将把这几个经常使用线程池整合到一个程序当中,
代码实例:
package com.xhj.thread; import java.util.Scanner; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * 几个经常使用线程池的理解与运用 * * @author XIEHEJUN * */ public class CreateThreadPools extends Thread { @Override public void run() { System.out.println("系统时间 : " + System.currentTimeMillis() + " 线程: " + Thread.currentThread().getName() + "正在执行!!"); } /** * 建立一个单线程的线程池 * * @return */ public ExecutorService SingleThreadPool() { ExecutorService singlePool = Executors.newSingleThreadExecutor(); return singlePool; } /** * 建立一个大小固定的线程池 * * @return */ public ExecutorService FixedThreadPool() { ExecutorService fixedPool = Executors.newFixedThreadPool(3); return fixedPool; } /** * 建立一个可缓存线程池 * * @return */ public ExecutorService CachedThreadPool() { ExecutorService cachedPool = Executors.newCachedThreadPool(); return cachedPool; } /** * 将建立好的线程放入线程池,并执行 * * @param pool */ public void service(ExecutorService pool) { // 建立线程 Thread thread1 = new CreateThreadPools(); Thread thread2 = new CreateThreadPools(); Thread thread3 = new CreateThreadPools(); Thread thread4 = new CreateThreadPools(); Thread thread5 = new CreateThreadPools(); // 线程入线程池,并执行 pool.execute(thread1); pool.execute(thread2); pool.execute(thread3); pool.execute(thread4); pool.execute(thread5); // 关闭线程池 pool.shutdown(); } /** * 建立一个大小无限制的线程池,可用与定时和周期性服务 */ public void scheduledThreadPool() { ScheduledThreadPoolExecutor scheduledPool = new ScheduledThreadPoolExecutor(1); scheduledPool.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("=======" + System.currentTimeMillis() + "========="); } }, 1000, 5000, TimeUnit.MILLISECONDS); scheduledPool.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println(System.nanoTime()); } }, 1000, 2000, TimeUnit.MILLISECONDS); } public static void main(String[] args) { CreateThreadPools creatThreadPool = new CreateThreadPools(); Scanner sc = new Scanner(System.in); while (true) { System.out.println("请选择建立线程池:1.单线程线程池;2.可缓存线程池;3.固定大小线程池;4可定时周期性执行线程池"); int i = sc.nextInt(); switch (i) { case 1: System.out.println("-----调用单线程的线程池-----"); // 调用单线程的线程池 creatThreadPool.service(creatThreadPool.SingleThreadPool()); break; case 2: System.out.println("-----调用可缓存线程的线程池-----"); // 调用可缓存线程的线程池 creatThreadPool.service(creatThreadPool.CachedThreadPool()); break; case 3: System.out.println("-----调用固定大小线程的线程池-----"); // 调用固定大小线程的线程池 creatThreadPool.service(creatThreadPool.FixedThreadPool()); break; case 4: System.out.println("-----调用大小无限制可定时和周期性执行的线程池-----"); // 调用固定大小线程的线程池 creatThreadPool.scheduledThreadPool(); break; } } } }
注:当线程池任务结束以后,必定要记得将线程池关闭,执行shutdown()方法。