java线程池概述
来源:互联网 发布:万网域名续费多少钱 编辑:程序博客网 时间:2024/06/13 09:21
池的概念不限于java语言,但是在java编程中我们经常会遇到各种池,数据库连接池(mysql,oracle,redis,mongodb,memcache),几乎没有web项目不使用到连接池的,再一个就是今天要说的线程池,在多线程编程中,线程需要不断的创建和销毁,这笔开销是很大的,如果控制不好,容易导致系统瘫痪。线程池技术,解决了多线程编程线程的创建,销毁的开销问题。
以上其实说明了线程池的使用场景:第一、单个任务执行时间短,很快完成,第二、任务量大。
线程池的思路:构建一些可用线程供使用,无需反复创建,使用完了归还,别的任务接着使用,在任务多的情况下他使用一个队列来做缓冲区。其实这个队列中保存的就是等待执行的任务线程,因此我们很容易理解BlockingQueue<Runnable>的含义,线程池示例如下所示:
package com.xxx.threadpool;import java.util.Scanner;import java.util.concurrent.Callable;import java.util.concurrent.CompletionService;import java.util.concurrent.ExecutorCompletionService;import java.util.concurrent.ExecutorService;import java.util.concurrent.Future;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class ThreadPoolExecutorMain {private ThreadPoolExecutorMain(){}private static CompletionService<Object> service;private static LinkedBlockingQueue<Runnable> queue;static{queue = new LinkedBlockingQueue<Runnable>();ExecutorService executorService = new ThreadPoolExecutor(1,3,60L,TimeUnit.SECONDS,queue);service = new ExecutorCompletionService<Object>(executorService);}public static Future<Object> execute(String taskName){return service.submit(new Callable<Object>() {@Overridepublic Object call() throws Exception {System.out.println("run for task : "+taskName);return "task-"+taskName;}});}@SuppressWarnings("resource")public static void main(String[] args) {String input = null;while(true){input = new Scanner(System.in).nextLine();if("exit".equals(input))break;execute(input);}}}
执行结果:
这个示例无法看出线程池的作用,几乎和普通的Thread或者实现了Runnable接口的线程没什么区别,只是感受一下线程池的创建和执行任务的过程。
下面介绍线程池的类型,java线程池api为我们提供了使用Executors来创建线程池,通过它可以创建以下类型的线程池。
线程池的类型:
1、fixedThreadPool,线程池中可用线程数目固定,超过数目的任务等待有可用线程时执行,在空闲时不会释放资源。
2、cachedThreadPool,线程数无限制,可以创建从0到Integer.MAX_VALUE的线程,在空闲时可以释放资源,但是如果后续又有任务来,又需要重新创建线程。
3、singleThreadPool,保证线程池中始终只有一个可用线程,如果线程异常结束,则会有另一个线程被创建,可以保证任务的顺序执行,在任意时间不会有多余的活动线程。
4、scheduledThreadPool,可以指定线程数量,他的应用场景是执行定时任务或者需要重复执行的任务。
通过以下部分源码可以看到:以上线程池的实现其实都是通过ThreadPoolExecutor来实现的,scheduledThreadPool更是实现了ScheduledExecutorService接口。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor implements ScheduledExecutorService
通过一个示例来说明线程池之间的区别:创建4个任务,分别执行4次打印信息,每次打印之前sleep 100ms,而我们创建的线程池个数可以设定为3(cachedThreadPool和singleThreadPool无须设置),程序代码如下:
package com.xxx.threadpool;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class ThreadPoolMain {private static void run(ExecutorService threadPool){for(int i=1;i<5;i++){final int taskId = i;threadPool.execute(new Runnable() {@Overridepublic void run() {for (int n = 1; n < 5; n++) {try {TimeUnit.MILLISECONDS.sleep(100);} catch (Exception e) {e.printStackTrace();}System.out.println("第"+taskId+"次任务,第"+n+"次执行");}}});}threadPool.shutdown();}public static void main(String[] args) {ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);ExecutorService cachedThreadPool = Executors.newCachedThreadPool();ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);run(fixedThreadPool);//先执行前面的三个任务,最后执行第四个任务run(cachedThreadPool);//四个任务几乎同时执行run(singleThreadPool);//四个任务按照顺序执行,线程池中只有一个线程可用,只能依次执行每一个任务run(scheduledThreadPool);//此种场景下和第一种线程池执行结果类似,先执行前面三个任务,最后执行第四个任务}}
每次只运行一个线程池查看打印信息,分别如下图所示:
在实际编程中,我们如何选择哪种线程池,其实不用过多的考虑,一般选择newFixedThreadPool(n),至于线程池中线程的个数,根据系统情况而定,一般为了充分利用系统cpu,编码中采用Runtime.getRuntime().availableProcessors()设置线程池的个数。
- java线程池概述
- Java线程之线程概述
- java 线程概述
- Java线程概述
- Java线程基本概述
- Java线程1:概述
- java线程概述
- Java守护线程概述
- 笔记-Java线程概述
- java线程概述
- 【线程】Java线程(2)-线程安全概述
- 【JAVA之多线程】1.概述
- Java之线程同步概述
- 线程池概述
- Java多线程线程池(1)--基本概述
- JAVA学习笔记之多线程专题(二):线程池概述
- 读书笔记-java网络编程-3线程-java线程概述
- Java进程和线程的概述
- JavaSE、JavaEE、JavaWeb分不清?
- WebSocket简单介绍
- linux下查找命令which/whereis/locate/find的对比和总结
- 为什么在Python里推荐使用多进程而不是多线程?
- Linux sed查看某时间段的系统日志
- java线程池概述
- JAVA中循环删除list中元素的方法总结
- 一屏展示多个li轮播设置demo
- swing 实现用户注册界面
- 【归纳】win7下caffe环境搭建与测试
- 我自己找的央视以及各大卫视的直播源(亲测可用)
- 正则化方法:L1和L2 regularization、数据集扩增、dropout
- Servlet生命周期
- Android TextView设置图片的大小