Java多线程/并发18、Java线程池
来源:互联网 发布:java面试视频 编辑:程序博客网 时间:2024/05/19 06:37
用过数据库的,都了解连接池概念。为了减少建立连接的开销,预先建立好多条连接,由连接池对象统一管理。当有进程需要连接数据库时,就分配一条空闲的连接给它,用完再被收回等待分配给下一个进程使用。
线程池的概念也一样,根据设置预先创建好一些线程,需要时就分配给你,使用完再收回,这样就不用老是去new Thread()了。
Java通过Executors提供四种线程池,分别为:
1、newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2、newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3、newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
4、newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
一、newCachedThreadPool 创建可缓存线程池
如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程
public class Executors2 { public static void main(String[] args) { ExecutorService threadPool = Executors.newCachedThreadPool(); for(int i=0;i<5;i++){ threadPool.execute(new myRunable()); } }}class myRunable implements Runnable { public void run() { System.out.println(Thread.currentThread().getName() + "执行"); }}
现在newCachedThreadPool创建了5个线程来处理输出任务:
pool-1-thread-1执行pool-1-thread-4执行pool-1-thread-3执行pool-1-thread-2执行pool-1-thread-5执行
现在我们让主线程休眠,放缓往线程池里往任务的节奏看看会是什么结果。修改main函数,让每次放入线程池后都休息一下
public static void main(String[] args) throws InterruptedException { ExecutorService threadPool = Executors.newCachedThreadPool(); for(int i=0;i<5;i++){ threadPool.execute(new myRunable()); Thread.sleep(1000); } }
现在newCachedThreadPool只创建了1个线程来处理输出任务
pool-1-thread-1执行pool-1-thread-1执行pool-1-thread-1执行pool-1-thread-1执行pool-1-thread-1执行
二、newFixedThreadPool 创建定长线程池
public class Executors1 { public static void main(String[] args) { ExecutorService threadPool = Executors.newFixedThreadPool(3); for(int i=0;i<7;i++){ threadPool.execute(new CustomerRunable()); } }}class CustomerRunable implements Runnable { public void run() { System.out.println(Thread.currentThread().getName() + "执行"); try { Thread.sleep(700); } catch (InterruptedException e) { e.printStackTrace(); } }}
结果:
pool-1-thread-1执行pool-1-thread-3执行pool-1-thread-2执行pool-1-thread-1执行pool-1-thread-3执行pool-1-thread-2执行pool-1-thread-2执行
可以看到,一共有三个线程来执行程序。
三、newScheduledThreadPool 创建定长周期性执行的线程池
该方法最常用的两种用法:
1、schedule(Runnable command,long delay, TimeUnit unit):指定多久之后运行
package JConcurrence.Study;import java.text.SimpleDateFormat;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class Executors2 { public static void main(String[] args) throws InterruptedException { ScheduledExecutorService scheduledThreadPool = Executors .newScheduledThreadPool(5); for (int i = 0; i < 5; i++) { scheduledThreadPool.schedule(new myRunable(), 5, TimeUnit.SECONDS); } SimpleDateFormat time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String TimeString = time.format(new java.util.Date()); System.out.println(Thread.currentThread().getName() + "运行时间是:"+TimeString); }}class myRunable implements Runnable { public void run() { SimpleDateFormat time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String TimeString = time.format(new java.util.Date()); System.out.println(Thread.currentThread().getName() + "运行时间是:"+TimeString); }}
输出
main运行时间是:2009-12-21 21:59:34pool-1-thread-1运行时间是:2009-12-21 21:59:39pool-1-thread-1运行时间是:2009-12-21 21:59:39pool-1-thread-1运行时间是:2009-12-21 21:59:39pool-1-thread-1运行时间是:2009-12-21 21:59:39pool-1-thread-1运行时间是:2009-12-21 21:59:39
2、scheduleAtFixedRate(Runnable command ,long initialDelay,long period, TimeUnit unit):指定多久之后以什么频率运行
把刚刚那一段中的
scheduledThreadPool.schedule(new myRunable(), 5, TimeUnit.SECONDS);
替换为
scheduledThreadPool.scheduleAtFixedRate(new myRunable(), 5,2, TimeUnit.SECONDS);
运行看看结果,可以发现源源不断的每隔2秒输出一次。
四、newSingleThreadExecutor 创建一个单线程化的线程池
用法和newCachedThreadPool没什么太大区别,只不过它只创建一个线程。
用它创建的线程池始终能保持一个存活的线程,如果该线程死了,也会重新生成一个
而自己new Thread出来的线程,如果挂了,就没有然后了。
代码和newCachedThreadPool类似,只是效果不同。不再举例。
五、配合ThreadFactory接口的使用
六、线程池中shutdown和shutdownNow的区别
shutDown()
当线程池调用该方法时,线程池的状态则立刻变成SHUTDOWN状态。此时,则不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionException异常。但是,此时线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出。
shutdownNow()
根据JDK文档描述,大致意思是:执行该方法,线程池的状态立刻变成STOP状态,并试图停止所有正在执行的线程,不再处理还在池队列中等待的任务,当然,它会返回那些未执行的任务。
它试图终止线程的方法是通过调用Thread.interrupt()方法来实现的,但是大家知道,这种方法的作用有限,如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt()方法是无法中断当前的线程的。所以,ShutdownNow()并不代表线程池就一定立即就能退出,它可能必须要等待所有正在执行的任务都执行完成了才能退出。
- Java多线程/并发18、Java线程池
- java多线程并发及线程池
- java多线程并发及线程池
- 【多线程高并发】java线程池
- java并发——多线程、线程池、并发集合
- Java多线程,线程同步synchronized,线程死锁【线程池常规用法】多线程并发处理
- Java多线程的深入讲解 -- 并发库,线程池等
- Java多线程与并发库高级应用之线程池
- Java多线程与并发库高级应用之线程池
- Java多线程与并发应用-(7)-线程池
- Java多线程与并发(六)之线程池
- java多线程并发(二)——线程池Executors
- JAVA多线程并发同步,以及线程终止
- Java并发线程--多线程的创建
- java并发多线程,线程的创建启动
- JavaSE:Java多线程并发和线程同步
- Java多线程/并发08、中断线程 interrupt()
- java多线程高并发线程安全问题
- A bug in PackageInstaller app. Relate to activity task affinity.
- 信息安全——非对称密码体制
- ZJOI2017Day2 游记
- JS判断一个字符串是否包含一个子串
- RBAC新解:基于资源的权限管理(Resource-Based Access Control)
- Java多线程/并发18、Java线程池
- ACM入门心得
- psutil--系统监控模块
- 我的阅读史(1)
- tomcat闪退
- H5播放视频插件
- java操作word生成水印升级版
- oracle数据类型varchar2、varchar、nvarchar2的区别
- 关于malloc实际分配内存的探讨