- 浏览: 1148339 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (138)
- JAVA基础 (22)
- Spring (6)
- 设计模式 (2)
- JDK源码 (3)
- java-功能组件 (4)
- 游戏项目 (2)
- linux (13)
- Oracle (2)
- struts (1)
- 字符集 (8)
- HTTP协议 (2)
- java-网络通信 (1)
- 工具软件推荐 (2)
- tomcat (1)
- java-容器框架 (2)
- java-IO框架 (2)
- java-多线程框架 (4)
- java-NIO框架 (0)
- jquery (2)
- 工具使用 (12)
- 加密解密 (1)
- redis (2)
- maven (2)
- svn (1)
- eclipse (1)
- mysql (11)
- 我的收藏 (1)
- JAVA进阶 (26)
- 运维 (3)
- protocol buffer (1)
- 优秀博主 (1)
- nginx (1)
- 算法 (2)
- 故障排查 (4)
- 粤语歌曲 (6)
- 生活总结 (6)
- 高并发 (4)
- 语言训练 (1)
- 读书笔记 (5)
- 诗歌 (1)
- tomcat源码学习 (1)
- 软件词汇 (1)
- git (1)
最新评论
-
ryuhi:
一个是来源source,一个是来源方序列号seq这两个数据要怎 ...
高并发的核心技术-幂等的实现方案 -
xuezhongyu01:
无量 写道Master-Gao 写道理论感觉还行,可以代码我还 ...
高并发的核心技术-幂等的实现方案 -
无量:
Master-Gao 写道理论感觉还行,可以代码我还是不会写。 ...
高并发的核心技术-幂等的实现方案 -
phil_jing:
@RequestParam 默认 true
SpringMVC注解@RequestParam全面解析 -
aguai0:
aguai0 写道第五条里的如果要获取任务执行结果,用Comp ...
JAVA进阶----ThreadPoolExecutor机制
创建线程以及管理线程池基本理解
参考原文链接:http://www.oschina.net/question/12_11255?sort=time
一、创建一个简单的java线程
在 Java 语言中,一个最简单的线程如下代码所示:
可通过下面一行代码来启动这个线程:
new Thread(runnable).start();
这是一个再简单不过的例子了,但如果你有许多需要长时间运行的任务同时执行,并需要等所有的这些线程都执行完毕,还想得到一个返回值,那么这就有点小小难度了。但 Java 已经有解决方案给你,那就是 Executors ,一个简单的类可以让你创建线程池和线程工厂。
二、Executors创建线程池
一个线程池使用类 ExecutorService 的实例来表示,通过 ExecutorService 你可以提交任务,并进行调度执行。下面列举一些你可以通过 Executors 类来创建的线程池的类型:
1.Single Thread Executor : 只有一个线程的线程池,因此所有提交的任务是顺序执行,代码:
2.Cached Thread Pool : 线程池里有很多线程需要同时执行,老的可用线程将被新的任务触发重新执行,如果线程超过60秒内没执行,那么将被终止并从池中删除,代码:
3.Fixed Thread Pool : 拥有固定线程数的线程池,如果没有任务执行,那么线程会一直等待,代码:
4.Scheduled Thread Pool : 用来调度即将执行的任务的线程池,代码:
5.Single Thread Scheduled Pool : 只有一个线程,用来调度执行将来的任务,代码:
三、主线程等待子线程结束各种方式
一旦你创建了一个线程池,你就可以往池中通过不同的方法提交执行任务,可提交 Runnable 或者 Callable 到线程池中,该方法返回一个 Future 实例表示任务的状态,如果你提交一个 Runnable ,那么如果任务完成后 Future 对象返回 null。
例如,你编写下面的 Callable:
如果你想使用4个线程来执行这个任务10次,那么代码如下:
ExecutorService pool = Executors.newFixedThreadPool(4);
for(int i = 0; i < 10; i++){
pool.submit(new StringTask());
}
但你必须手工的关闭线程池来结束所有池中的线程:
pool.shutdown();
如果你不这么做,JVM 并不会去关闭这些线程;另外你可以使用 shutdownNow() 的方法来强制关闭线程池,那么执行中的线程也会被中断,所有尚未被执行的任务也将不会再执行。
但这个例子中,你无法获取任务的执行状态,因此我们需要借助 Future 对象:
下面的例子同时可以阻塞主线程等待子线程完成,但是该方式,如果阻塞的第一个线程很久,可能其他线程已经执行完了,很多情况不太适用
不过这段代码稍微有点复杂,而且有不足的地方。如果第一个任务耗费非常长的时间来执行,然后其他的任务都早于它结束,那么当前线程就无法在第一个任务结束之前获得执行结果,但是别着急,Java 为你提供了解决方案——CompletionService。
一个 CompletionService 就是一个服务,用以简化等待任务的执行结果,实现的类是 ExecutorCompletionService,该类基于 ExecutorService,因此我们可试试下面的代码:
通过这段代码,我们可以根据执行结束的顺序获取对应的结果,而无需维护一个 Future 对象的集合。
这就是本文的全部,通过 Java 为我们提供的各种工具,可以方便的进行多任务的编程,通过使用 Executors、ExecutorService 以及 CompletionService 等工具类,我们可以创建复杂的并行任务执行算法,而且可以轻松改变线程数。
上面的方式还有问题,就是主线程放了好多任务,这个时间和任务量可能非常大,后面的获取结果一直等待,结果队列很大,会有很多问题,这里要单独开一个结果获取线程更好,哪天继续写完这个方案,还有好几种
参考原文链接:http://www.oschina.net/question/12_11255?sort=time
一、创建一个简单的java线程
在 Java 语言中,一个最简单的线程如下代码所示:
Runnable runnable = new Runnable(){ public void run(){ System.out.println("Run"); } }
可通过下面一行代码来启动这个线程:
new Thread(runnable).start();
这是一个再简单不过的例子了,但如果你有许多需要长时间运行的任务同时执行,并需要等所有的这些线程都执行完毕,还想得到一个返回值,那么这就有点小小难度了。但 Java 已经有解决方案给你,那就是 Executors ,一个简单的类可以让你创建线程池和线程工厂。
二、Executors创建线程池
一个线程池使用类 ExecutorService 的实例来表示,通过 ExecutorService 你可以提交任务,并进行调度执行。下面列举一些你可以通过 Executors 类来创建的线程池的类型:
1.Single Thread Executor : 只有一个线程的线程池,因此所有提交的任务是顺序执行,代码:
Executors.newSingleThreadExecutor()
2.Cached Thread Pool : 线程池里有很多线程需要同时执行,老的可用线程将被新的任务触发重新执行,如果线程超过60秒内没执行,那么将被终止并从池中删除,代码:
Executors.newCachedThreadPool()
3.Fixed Thread Pool : 拥有固定线程数的线程池,如果没有任务执行,那么线程会一直等待,代码:
Executors.newFixedThreadPool()
4.Scheduled Thread Pool : 用来调度即将执行的任务的线程池,代码:
Executors.newScheduledThreadPool()
5.Single Thread Scheduled Pool : 只有一个线程,用来调度执行将来的任务,代码:
Executors.newSingleThreadScheduledExecutor()
三、主线程等待子线程结束各种方式
一旦你创建了一个线程池,你就可以往池中通过不同的方法提交执行任务,可提交 Runnable 或者 Callable 到线程池中,该方法返回一个 Future 实例表示任务的状态,如果你提交一个 Runnable ,那么如果任务完成后 Future 对象返回 null。
例如,你编写下面的 Callable:
private final class StringTask extends Callable<String>{ public String call(){ //Long operations return "Run"; } }
如果你想使用4个线程来执行这个任务10次,那么代码如下:
ExecutorService pool = Executors.newFixedThreadPool(4);
for(int i = 0; i < 10; i++){
pool.submit(new StringTask());
}
但你必须手工的关闭线程池来结束所有池中的线程:
pool.shutdown();
如果你不这么做,JVM 并不会去关闭这些线程;另外你可以使用 shutdownNow() 的方法来强制关闭线程池,那么执行中的线程也会被中断,所有尚未被执行的任务也将不会再执行。
但这个例子中,你无法获取任务的执行状态,因此我们需要借助 Future 对象:
下面的例子同时可以阻塞主线程等待子线程完成,但是该方式,如果阻塞的第一个线程很久,可能其他线程已经执行完了,很多情况不太适用
ExecutorService pool = Executors.newFixedThreadPool(4); List<Future<String>> futures = new ArrayList<Future<String>>(10); for(int i = 0; i < 10; i++){ futures.add(pool.submit(new StringTask())); } for(Future<String> future : futures){ String result = future.get(); //Compute the result } pool.shutdown();
不过这段代码稍微有点复杂,而且有不足的地方。如果第一个任务耗费非常长的时间来执行,然后其他的任务都早于它结束,那么当前线程就无法在第一个任务结束之前获得执行结果,但是别着急,Java 为你提供了解决方案——CompletionService。
一个 CompletionService 就是一个服务,用以简化等待任务的执行结果,实现的类是 ExecutorCompletionService,该类基于 ExecutorService,因此我们可试试下面的代码:
ExecutorService threadPool = Executors.newFixedThreadPool(4); CompletionService<String> pool = new ExecutorCompletionService<String>(threadPool); for(int i = 0; i < 10; i++){ pool.submit(new StringTask()); } for(int i = 0; i < 10; i++){ String result = pool.take().get(); //Compute the result } threadPool.shutdown();
通过这段代码,我们可以根据执行结束的顺序获取对应的结果,而无需维护一个 Future 对象的集合。
这就是本文的全部,通过 Java 为我们提供的各种工具,可以方便的进行多任务的编程,通过使用 Executors、ExecutorService 以及 CompletionService 等工具类,我们可以创建复杂的并行任务执行算法,而且可以轻松改变线程数。
上面的方式还有问题,就是主线程放了好多任务,这个时间和任务量可能非常大,后面的获取结果一直等待,结果队列很大,会有很多问题,这里要单独开一个结果获取线程更好,哪天继续写完这个方案,还有好几种
发表评论
-
区块链!每个人都要了解下--十分钟洞见区块链的前世今生
2018-04-27 12:32 803区块链!每个人都要了解下--十分钟洞见区块链的前世今生 ... -
区块链!每个人都要了解下--十分钟洞见区块链的前世今生
2018-04-27 12:09 0为啥要讲区块链呢,因为它太火了,火到什么程度呢 ... -
项目打包,报软件包、类不存在问题排查过程
2017-05-16 17:13 5989项目打包报,软件包、类不存在问题排查过程 一、背景 ... -
海量数据存储--分库分表策略详解
2017-04-12 19:59 7337海量数据存储--分库分表策略详解 一、背景: 系统刚 ... -
jstack详解
2017-02-17 11:15 1918jstack http://www.open-open.co ... -
jdk-源码中的一些坑
2017-02-13 15:17 1255jdk-源码中的一些坑 1. Runnable接口的命名简直 ... -
一次mysql死锁的排查过程
2016-11-21 10:04 11343一次mysql死锁的排查过程 一、背景 17号晚上要吃饭 ... -
JVM调优:选择合适的GC collector (三)
2016-11-15 20:51 1277CMS Collector 在很多地方,CMS Collec ... -
JVM调优:选择合适的GC collector (二)
2016-11-15 20:47 1001http://blog.csdn.net/historya ... -
JVM调优:选择合适的GC collector (一)
2016-11-15 20:45 1276http://blog.csdn.net/historyas ... -
jstat查看gc情况
2016-11-10 10:11 2498jps(Java Virtual Machine Proces ... -
tomcat源码学习(一) eclipse导入tomcat源码
2016-10-31 20:05 14191. 到官网下载Tomcat源代码,这里用到的是apache- ... -
深入分析ClassLoader
2016-10-27 23:27 786转(原文http://blog.csdn.net/xya ... -
业务架构模板
2016-10-20 19:56 1913业务架构模板 默认一个高大上的业务系统需要具备的技术点和对应 ... -
如何写一个强壮的JOB任务
2016-10-18 15:00 3020如何写一个强壮的JOB任务 1. JOB跑一半断电了,不能产 ... -
mybatis.xml中sql编写规范
2016-10-18 14:54 6263一、越少的代码,越强悍的功能,xml里面应该6个sql语句就够 ... -
数据库设计规范
2016-10-17 23:29 65861. 数据库设计基本规范 领域驱动表内容 ... -
全局主键生成器-支持单JVM1秒近1000万订单生成
2016-05-03 20:46 5683全局主键生成器 介绍: 相对于DB自增序列的全局主键生成器, ... -
解决并发下累计的问题
2016-04-25 11:58 2129package com.tongbanjie.trade.te ... -
系统开发中的坑
2016-03-15 15:39 2807系统开发中的坑 这个是在公司分享的一个ppt,整理下发到博客里 ...
相关推荐
Java进阶学习教程中的第13章主要涵盖了JVM(Java虚拟机)和多线程两个核心概念。JVM是Java程序运行的基础,它负责解释执行字节码文件,并提供了Java语言的跨平台特性。Java程序通过JVM与操作系统交互,使得程序可以...
NIO提供了一种新的I/O模型,允许服务器在不阻塞主线程的情况下处理多个客户端连接。Selector和Channel是NIO的核心组件,Selector负责监控多个通道,而通道则用于读写数据。 对于高级服务器应用,如Web服务器,Java...
- **每个Java程序都至少有一个线程**:当Java程序启动时,JVM(Java虚拟机)会创建一个主线程来执行程序的`main()`方法。此外,JVM还会为垃圾回收、对象终止等内部任务创建额外的线程。 - **创建新线程的方法**: ...
- **线程的概念**:线程是程序执行流的最小单位,一个标准的Java应用程序至少有一个线程,即主线程。 - **创建线程的方式**: - 继承`Thread`类。 - 实现`Runnable`接口。 - 使用`Callable`与`Future`。 - 使用`...
主线程负责创建其他子线程,并且通常需要最后完成执行,因为它需要执行各种关闭操作,确保所有资源被正确释放。 #### Thread类 Java 提供了 `java.lang.Thread` 类来支持多线程编程。通过这个类,开发者可以轻松地...
在Java中,每个应用程序至少有一个主线程,用于执行程序的主要逻辑。通过创建额外的线程,可以实现并发执行,提高程序响应速度。 2. **线程的创建**: - **继承Thread类**:创建一个新的类,该类继承自`Thread`类...
Java中的每一个进程至少包含一个线程,即主线程,主线程负责执行程序的main()方法。 **Java中的线程** 1. **主线程**:JVM启动时会创建一个主线程,负责执行程序的main方法。同时,JVM还会创建其他线程,如垃圾回收...
《JAVA2实用教程(第5版)》是耿祥义教授编著的一本经典Java编程教材,适合初学者和进阶者深入理解Java语言。这本书以其深入浅出的讲解方式和丰富的实例,深受广大读者喜爱。课后习题是学习过程中不可或缺的部分,它...
1. **线程的概念**:在Java中,线程是程序执行流的最小单元,一个标准的Java应用程序至少有一个线程,即主线程(main thread)。Java中的线程可以通过实现`Runnable`接口或者继承`Thread`类来创建。 2. **线程的...
Java多线程知识的理解0.前言1.从一道题目引入2.创建线程2.1.继承Thread类2.2.实现Runnable接口3.线程的生命周期4.线程安全4.1.为什么需要线程安全?4.2.如何实现线程安全?...为什么主线程早于子线
这种多线程并行的概念可以帮助主线程专注于处理UI事件,同时让子线程处理后台任务。 - **子线程的作用**:例如,播放动画背景音乐或从网络下载视频等耗时操作可以通过子线程完成,这样主线程可以更高效地处理用户...
- **Handler/Looper**:主线程和子线程间的通信机制。 - **IntentService**:后台服务,适合执行耗时操作。 6. **权限管理**: - **运行时权限**:Android 6.0及以上版本需要在运行时动态申请权限。 7. **...
注解需要指定`threadMode`参数,用于指定事件处理所在的线程(主线程、后台线程等)。 5. **注册/注销订阅者**:在订阅者类的生命周期方法中,如Activity的`onCreate()`和`onDestroy()`,分别调用`EventBus.get...
8. **多线程与线程池**:理解Android中的主线程与工作线程的区别,以及如何使用Handler、Runnable、Thread、ExecutorService来实现多线程操作,提高应用性能。 9. **权限管理**:Android 6.0(API 23)引入了运行时...
通过`AsyncContext`接口,开发者可以在后台执行任务,而不阻塞主线程。 7. **Session管理**:Servlet通过HttpSession接口管理用户会话。理解如何正确设置和管理session,避免session劫持和session固定攻击,是Web...
- 理解主线程和工作线程的区别。 - 使用Handler和Looper进行消息传递。 - AsyncTask:简化异步任务的处理方式。 - Java 8的新特性:如CompletableFuture等高级并发工具。 5. **跨进程通信**: - Intent:不仅...
这在多线程环境中非常有用,可以确保主线程在执行某些操作之前,等待其他线程完成其任务,从而避免数据不一致或竞争条件等问题。 #### ThreadDemo6.java - 线程控制与资源管理 虽然`ThreadDemo6.java`的代码片段未...
`AsyncTask`是Android提供的一种轻量级的异步处理机制,它可以帮助开发者在后台线程执行任务,然后在主线程更新UI,避免了因长时间阻塞主线程而造成的ANR(Application Not Responding)错误。下面我们将详细探讨`...