JAVA线程池应用的DEMO
在做很多高并发应用的时候,单线程的瓶颈已经满足不了我们的需求,此时使用多线程来提高处理速度已经是比较常规的方案了。在使用多线程的时候,我们可以使用线程池来管理我们的线程,至于使用线程池的优点就不多说了。
Java线程池说起来也简单,简单说下继承关系:
ThreadPoolExecutor extends AbstractExecutorService implements ExecutorService extends Executor
还有一个支持延时执行线程和可以重复执行线程的实现类:
ScheduledThreadPoolExecutor extends ThreadPoolExecutor implements ScheduledExecutorService
大家把这些类中的相关方法弄清楚,使用线程池就不在话下了。其实弄清楚里面各个方法的功能也就够了。
最重要的还是在实践中总结经验,企业需要的是能实际解决问题的人。
下面是我写的一个例子,包括3个Java文件,分别是:
ExecutorServiceFactory.java
ExecutorProcessPool.java
ExecutorTest.java
1、ExecutorServiceFactory
package test; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger; /**
* 线程池构造工厂
*
* @author allan
* @date 2017年3月20日
*/
public class ExecutorServiceFactory {
private static ExecutorServiceFactory executorFactory = new ExecutorServiceFactory();
/**
* 定时任务线程池
*/
private ExecutorService executors; private ExecutorServiceFactory() {
} /**
* 获取ExecutorServiceFactory
*
* @return
*/
public static ExecutorServiceFactory getInstance() {
return executorFactory;
} /**
* 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
*
* @return
*/
public ExecutorService createScheduledThreadPool() {
// CPU个数
int availableProcessors = Runtime.getRuntime().availableProcessors();
// 创建
executors = Executors.newScheduledThreadPool(availableProcessors * 10, getThreadFactory());
return executors;
} /**
* 创建一个使用单个 worker 线程的
* Executor,以无界队列方式来运行该线程。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程,
* 那么如果需要,一个新线程将代替它执行后续的任务)。可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。与其他等效的
* newFixedThreadPool(1) 不同,可保证无需重新配置此方法所返回的执行程序即可使用其他的线程。
*
* @return
*/
public ExecutorService createSingleThreadExecutor() {
// 创建
executors = Executors.newSingleThreadExecutor(getThreadFactory());
return executors;
} /**
* 创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用
* execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60
* 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。注意,可以使用 ThreadPoolExecutor
* 构造方法创建具有类似属性但细节不同(例如超时参数)的线程池。
*
* @return
*/
public ExecutorService createCachedThreadPool() {
// 创建
executors = Executors.newCachedThreadPool(getThreadFactory());
return executors;
} /**
* 创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads
* 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务
* ,则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止
* ,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在。
*
* @return
*/
public ExecutorService createFixedThreadPool(int count) {
// 创建
executors = Executors.newFixedThreadPool(count, getThreadFactory());
return executors;
} /**
* 获取线程池工厂
*
* @return
*/
private ThreadFactory getThreadFactory() {
return new ThreadFactory() {
AtomicInteger sn = new AtomicInteger();
public Thread newThread(Runnable r) {
SecurityManager s = System.getSecurityManager();
ThreadGroup group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
Thread t = new Thread(group, r);
t.setName("任务线程 - " + sn.incrementAndGet());
return t;
}
};
}
}
2、ExecutorProcessPool
package test; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future; /**
* 线程处理类
*
* @author allan
* @date 2017年3月20日
*/
public class ExecutorProcessPool { private ExecutorService executor;
private static ExecutorProcessPool pool = new ExecutorProcessPool();
private final int threadMax = 10; private ExecutorProcessPool() {
System.out.println("threadMax>>>>>>>" + threadMax);
executor = ExecutorServiceFactory.getInstance().createFixedThreadPool(threadMax);
} public static ExecutorProcessPool getInstance() {
return pool;
} /**
* 关闭线程池,这里要说明的是:调用关闭线程池方法后,线程池会执行完队列中的所有任务才退出
*
* @author allan
* @date 2017年3月20日
*/
public void shutdown(){
executor.shutdown();
} /**
* 提交任务到线程池,可以接收线程返回值
*
* @param task
* @return
* @author allan
* @date 2017年3月20日
*/
public Future<?> submit(Runnable task) {
return executor.submit(task);
} /**
* 提交任务到线程池,可以接收线程返回值
*
* @param task
* @return
* @author allan
* @date 2017年3月20日
*/
public Future<?> submit(Callable<?> task) {
return executor.submit(task);
} /**
* 直接提交任务到线程池,无返回值
*
* @param task
* @author allan
* @date 2017年3月20日
*/
public void execute(Runnable task){
executor.execute(task);
} }
3、ExecutorTest
package test; import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; /**
* 测试类
*
* @author allan
* @date 2017年3月20日
*/
public class ExecutorTest { public static void main(String[] args) { ExecutorProcessPool pool = ExecutorProcessPool.getInstance(); for (int i = 0; i < 200; i++) {
Future<?> future = pool.submit(new ExcuteTask1(i+""));
// try {
// 如果接收线程返回值,future.get() 会阻塞,如果这样写就是一个线程一个线程执行。所以非特殊情况不建议使用接收返回值的。
// System.out.println(future.get());
// } catch (Exception e) {
// e.printStackTrace();
// }
} for (int i = 0; i < 200; i++) {
pool.execute(new ExcuteTask2(i+""));
} //关闭线程池,如果是需要长期运行的线程池,不用调用该方法。
//监听程序退出的时候最好执行一下。
pool.shutdown();
} /**
* 执行任务1,实现Callable方式
*
* @author allan
* @date 2017年3月20日
*/
static class ExcuteTask1 implements Callable<String> {
private String taskName; public ExcuteTask1(String taskName) {
this.taskName = taskName;
} @Override
public String call() throws Exception {
try {
// Java 6/7最佳的休眠方法为TimeUnit.MILLISECONDS.sleep(100);
// 最好不要用 Thread.sleep(100);
TimeUnit.MILLISECONDS.sleep((int)(Math.random() * 1000));// 1000毫秒以内的随机数,模拟业务逻辑处理
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("-------------这里执行业务逻辑,Callable TaskName = " + taskName + "-------------");
return ">>>>>>>>>>>>>线程返回值,Callable TaskName = " + taskName + "<<<<<<<<<<<<<<";
}
} /**
* 执行任务2,实现Runable方式
*
* @author allan
* @date 2017年3月20日
*/
static class ExcuteTask2 implements Runnable {
private String taskName; public ExcuteTask2(String taskName) {
this.taskName = taskName;
} @Override
public void run() {
try {
TimeUnit.MILLISECONDS.sleep((int)(Math.random() * 1000));// 1000毫秒以内的随机数,模拟业务逻辑处理
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("-------------这里执行业务逻辑,Runnable TaskName = " + taskName + "-------------");
} }
}
原文:http://blog.csdn.net/catoop/article/details/50180949
另外推荐一篇:ExecutorService中submit和execute的区别
JAVA线程池应用的DEMO的更多相关文章
- java线程池,信号量使用demo
直接上代码 package org.jimmy.threadtest20181121; import java.util.concurrent.LinkedBlockingQueue; import ...
- 这么说吧,java线程池的实现原理其实很简单
好处 : 线程是稀缺资源,如果被无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,合理的使用线程池对线程进行统一分配.调优和监控,有以下好处: 1.降低资源消耗: 2.提高响应速度: 3.提高线 ...
- 深入分析java线程池的实现原理(转载)
前言 线程是稀缺资源,如果被无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,合理的使用线程池对线程进行统一分配.调优和监控,有以下好处: 1.降低资源消耗: 2.提高响应速度: 3.提高线程的 ...
- Java线程池 详解(图解)
来源:www.jianshu.com/p/098819be088c 拓展: 手动创建 new ThreadPoolExecutor 的使用: https://segmentfault.com/a/11 ...
- Java线程池使用和源码分析
1.为什么使用线程池 在多线程编程中一项很重要的功能就是执行任务,而执行任务的方式有很多种,为什么一定需要使用线程池呢?下面我们使用Socket编程处理请求的功能,分别对每种执行任务的方式进行分析. ...
- java 线程池第一篇 之 ThreadPoolExcutor
一:什么是线程池? java 线程池是将大量的线程集中管理的类,包括对线程的创建,资源的管理,线程生命周期的管理.当系统中存在大量的异步任务的时候就考虑使用java线程池管理所有的线程.减少系统资源的 ...
- 面试必备:Java线程池解析
前言 掌握线程池是后端程序员的基本要求,相信大家求职面试过程中,几乎都会被问到有关于线程池的问题.我在网上搜集了几道经典的线程池面试题,并以此为切入点,谈谈我对线程池的理解.如果有哪里理解不正确,非常 ...
- Java线程池实现
电脑的CPU资源是有限的,任务的处理速度与线程数量之间并不是正相关.当线程数量过多,CPU要频繁的在不同线程切换,反而会引起处理性能的下降.线程池中最大的线程数,是考虑多种因素来事先设定的,比如硬件的 ...
- Java线程池 ThreadPoolExecutor类
什么是线程池? java线程池是将大量的线程集中管理的类, 包括对线程的创建, 资源的管理, 线程生命周期的管理. 当系统中存在大量的异步任务的时候就考虑使用java线程池管理所有的线程, 从而减少系 ...
随机推荐
- Datatables快速入门开发--一款好用的JQuery表格插件
博主是一个java后端程序员小白,前端技术会用但不精通,做后台的一些功能经常要涉及表格的展示,分页,搜索,排序等等一系列功能,在经历了一段时间的原始手段,开始接触并使用Datatables,一个jqu ...
- 3.commonjs模块
1.首先建一个math.js exports.add = function(a, b){ return a + b; } exports.sub = function(a, b){ return a ...
- Locust性能测试工具的安装及实际应用
一.安装Locust 安装Locust之前先安装的库:gevent库:第三方库,gevent为python提供了比较完善的协程支持.使用gevent,可以获得极高的并发性能. pip install ...
- 以太网帧、TCP与UDP段以及IP数据报格式总结
传输层及其以下的机制由内核提供,是操作系统的一部分,应⽤层由⽤户进程提供应⽤层数据通过协议栈发到⽹络上时,每层协议都要加上⼀个数据⾸部(header),称为封装.不同的协议层对数据包有不同的称谓,在传 ...
- [bzoj4832]抵制克苏恩 概率dp
考试的时候打了个搜索,时间比较短,样例又非常的弱,实在不太清楚他这个到底是什么意思. 不过lc大神好腻害,讲解了一下非常的清楚了. f[i][j][k][l]表示第i次伤害(啊),一滴血j个,两滴血k ...
- PL/SQL 编程(一)基础,变量,分支,循环,异常
SQL和PL/SQL: SQL 结构化查询语言(Structural Query Language),是用来访问和操作关系型数据库的一种标准通用语言,属于第四代语言(4GL).可以方便的调用相应语句来 ...
- 从Google Play下载应用并不安全,上千款监视软件伪装其中
如果你认为在官方应用市场里下载app就觉得安全的话,小编可以负责任的回答你:"too young too simple,sometimes native" 今年4月,BankBot ...
- Orleans稍微复杂的例子—互动
这是Orleans系列文章中的一篇.首篇文章在此 我费力费心的翻译过官方的教程,但是本人英语词汇量不高,可是架不住电子词典啊-只要肯花时间,我这些内容谁都可以做出来.所以这个事例告诉我们一个道理,那就 ...
- python之--------封装
一.封装: 什么是封装呢?(封装不是单纯意义的隐藏,其实它还是可以查看的) 就是把一些不想让别人看的给隐藏起来了 封装数据:目的是保护隐私 功能封装:目的是隔离复杂度 如果用了私有的,在类的外部,无法 ...
- 前端性能优化--图片处理(Css Sprites 与 base64)
前言: 近期研究着前端性能的优化方面的知识,并以博客记之.之前有相同系列的文章(前端性能优化--图片懒加载(lazyload image)),这次继续是关于图片的处理,css sprites 和 ba ...