java线程池的几种使用方式和场景
一、线程池使用场景
- 单个任务处理时间短
- 将需处理的任务数量大
二、使用Java线程池好处
1.使用new Thread()创建线程的弊端:
- 每次通过new Thread()创建对象性能不佳。
- 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。
- 缺乏更多功能,如定时执行、定期执行、线程中断。
2.使用Java线程池的好处:
- 重用存在的线程,减少对象创建、消亡的开销,提升性能。
- 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
- 提供定时执行、定期执行、单线程、并发数控制等功能。
Java四种线程池
Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。下面这张图完整描述了线程池的类体系结构:
1. newCachedThreadPool
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。
public static ExecutorService newCachedThreadPool()
示例代码:
public class ThreadPoolExecutorTest { public static void main(String[] args ) { ExecutorService cacheThreadPool =Executors.newCachedThreadPool(); for(int i =1;i<=5;i++){ final int index=i ; try{ Thread.sleep(1000); }catch(InterruptedException e ) { e.printStackTrace(); } cacheThreadPool.execute(new Runnable(){ @Override public void run() { System.out.println("第" +index +"个线程" +Thread.currentThread().getName()); } }); } } } //输出结果 第1个线程pool-1-thread-1 第2个线程pool-1-thread-1 第3个线程pool-1-thread-1 第4个线程pool-1-thread-1 第5个线程pool-1-thread-1由结果可看出 当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
2. newFixedThreadPool
创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
public static ExecutorService newFixedThreadPool(int nThreads)
nThreads - 池中的线程数
示例代码:
public class ThreadPoolExecutorTest { public static void main(String[] args) { ExecutorService fixedThreadPool =Executors. newFixedThreadPool(3); for (int i =1; i<=5;i++){ final int index=i ; fixedThreadPool.execute(new Runnable(){ @Override public void run() { try { System.out.println("第" +index + "个线程" +Thread.currentThread().getName()); Thread.sleep(1000); } catch(InterruptedException e ) { e .printStackTrace(); } } }); } } }由于设置最大线程数为3,所以在输出三个数后等待2秒后才继续输出。
2. newScheduledThreadPool
创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
corePoolSize - 池中所保存的线程数,即使线程是空闲的也包括在内。
延迟执行示例代码:
public class ThreadPoolExecutorTest { public static void main(String[] args) { ScheduledExecutorService scheduledThreadPool= Executors.newScheduledThreadPool(3); scheduledThreadPool.schedule(newRunnable(){ @Override public void run() { System.out.println("延迟三秒"); } }, 3, TimeUnit.SECONDS); } }表示延迟3秒执行。
定期执行示例代码:
public class ThreadPoolExecutorTest { public static void main(String[] args) { ScheduledExecutorService scheduledThreadPool= Executors.newScheduledThreadPool(3); scheduledThreadPool.scheduleAtFixedRate(newRunnable(){ @Override public void run() { System.out.println("延迟1秒后每三秒执行一次"); } },1,3,TimeUnit.SECONDS); } }表示延迟1秒后每3秒执行一次。
4.newSingleThreadExecutor
创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程,那么如果需要,一个新线程将代替它执行后续的任务)。可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。与其他等效的 newFixedThreadPool(1)不同,可保证无需重新配置此方法所返回的执行程序即可使用其他的线程。
示例代码:
public class ThreadPoolExecutorTest { public static void main(String[] args) { ExecutorService singleThreadPool= Executors.newSingleThreadExecutor(); for(int i=1;i<=5;i++){ int index=i; singleThreadPool.execute(new Runnable(){ @Override public void run() { try{ System.out.println("第"+index+"个线程"); Thread.sleep(2000); }catch(InterruptedException e) { e.printStackTrace(); } } }); } } }
- Java枚举的几种使用方式
- JAVA使用XFire开发Web Service客户端几种调用方式
- Java的jdbc使用addBatch进行批处理操作的几种方式
- Android数据通信--USB通信的几种方式及使用场景
- JAVA使用XFire开发Web Service客户端几种调用方式
- JAVA 使用线程的几种方式
- Java多线程有哪几种实现方式? Java中的类如何保证线程安全? 请说明ThreadLocal的用法和适用场景(面试题)
- java中线程池的几种实现方式
- Java使用HttpClient发送请求的几种常用方式
- 前端html向后端java传递数据的几种方式(暂时使用到)
- Java多线程有哪几种实现方式? Java中的类如何保证线程安全? 请说明ThreadLocal的用法和适用场景
- 整理MINGW编译dll使用JNI被java调用的几种方式
- 干货:Java几种线程池的分析和使用。
- java当中的定时器的几种使用方式
- java使用JDBC连接数据库的几种方式
- Java Executor并发框架(十四)Executor框架线程池使用原始方式实现生产者消费者模式
- java线程池使用场景和使用方法较详细文摘
- java读写文件的几种方式(不断完善),方便日后使用
- java ThreadLocal(应用场景及使用方式及原理)
- java中使用mongodb的几种方式