Java高并发编程(四)
一、Executor执行器
1.Executor接口,java线程池框架中的顶层接口,提供一个execute方法来执行任务
import java.util.concurrent.Executor;
public class T01_MyExecutor implements Executor {
public static void main(String[] args) {
new T01_MyExecutor().execute(()->System.out.println("hello executor"));
}
@Override
public void execute(Runnable command) {
//new Thread(command).run();//另起线程方法调用
command.run();//方法直接调用
}
}
2.任务接口
1)callable接口:提供一个call方法,具有返回值可以抛出异常
2)runnable接口:提供一个run方法,无返回值不可抛出异常
3.ExecutorService接口(Executor的一个子接口)
1)ExecutorService可以理解为服务,执行execute方法可以向服务器中添加runnable任务无返回值,而执行submit方法可以向服务中添加callable与runnable任务,且有返回值
2)Executor与ExecutorService的简单理解:可以想象许多的执行器Executor在等待着执行任务,而service服务可通过调用execute或submit方法来添加不同的任务供执行器执行
3)submit方法具有一个future类型的返回值,与callable,Executors一起使用
public class T06_Future {
public static void main(String[] args) throws InterruptedException, ExecutionException {
FutureTask<Integer> task = new FutureTask<>(()->{
TimeUnit.MILLISECONDS.sleep(500);
return 1000;
}); //new Callable () { Integer call();}
new Thread(task).start();
System.out.println(task.get()); //阻塞
//*******************************
ExecutorService service = Executors.newFixedThreadPool(5);
Future<Integer> f = service.submit(()->{
TimeUnit.MILLISECONDS.sleep(500);
return 1;
});
System.out.println(f.get());
System.out.println(f.isDone());
}
}
运行结果:

4.Executors(操作Executor的一个工具类、工厂类)
二、ThreadPool线程池
1.线程池将任务分配给池中线程,当线程池中线程执行不过来时,任务会进入等待队列,队列由BlockingQueue实现,当有线程空闲时再来任务时会被分配给空闲线程,一个线程同时维护着两个队列(结束队列与等待队列)
下面一个程序帮助理解线程池的概念
public class T05_ThreadPool {
public static void main(String[] args) throws InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(5); //execute submit
for (int i = 0; i < 6; i++) {
service.execute(() -> {
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
});
}
System.out.println(service);
service.shutdown();//正常关闭,等待所有任务执行完毕,关闭线程池
System.out.println(service.isTerminated());//判断所有任务是否都执行完了
System.out.println(service.isShutdown());//判断线程池是否被关闭了
System.out.println(service);
TimeUnit.SECONDS.sleep(5);
System.out.println(service.isTerminated());
System.out.println(service.isShutdown());
System.out.println(service);
}
}
运行结果:

2.六种线程池
1)FixedThreadPool 固定线程数量的线程池
2)cachedThreadPool 假定刚开始一个线程都没有,来一个任务开启一个线程,如果再来一个任务,线程池中有空闲线程就将任务分配给空闲线程,如此往复直到起到电脑能支撑限度为止,默认一个线程空闲超过一分钟就自动销毁
3)singleThreadPool 线程池中只有一个线程
4)scheduledThreadPool 定时器线程池
5)workStealingPool 工作窃取线程池,当前线程池有线程空闲,会自动去寻找任务执行,默认根据CPU核数启动默认线程数目线程,是精灵(demon)线程(守护线程、后台线程),主函数不阻塞的话看不到输出,本质上是ForkJoinPool实现的
6)ForkJoinPool 分叉合并线程,大任务可以切分成许多的小任务,如果小任务还是太大的话还可以继续分,分的可以了就将小任务合并,最后产生一个总的结果(有点像归并排序)
ForkJoinTask从RecursiveAction和RecursiveTask继承
a.RecursiveAction 无返回值
/**
* 对数组中所有数求和
* @author zhangqi
*
*/
public class T12_ForkJoinPool {
static int[] nums = new int[1000000];
static final int MAX_NUM = 50000;
static Random r = new Random(); static {
for(int i=0; i<nums.length; i++) {
nums[i] = r.nextInt(100);
} System.out.println(Arrays.stream(nums).sum()); //stream api
} static class AddTask extends RecursiveAction { int start, end; AddTask(int s, int e) {
start = s;
end = e;
} @Override
protected void compute() { if(end-start <= MAX_NUM) {
long sum = 0L;
for(int i=start; i<end; i++) sum += nums[i];
System.out.println("from:" + start + " to:" + end + " = " + sum);
} else { int middle = start + (end-start)/2; AddTask subTask1 = new AddTask(start, middle);
AddTask subTask2 = new AddTask(middle, end);
subTask1.fork();
subTask2.fork();
} } } /*static class AddTask extends RecursiveTask<Long> { int start, end; AddTask(int s, int e) {
start = s;
end = e;
} @Override
protected Long compute() { if(end-start <= MAX_NUM) {
long sum = 0L;
for(int i=start; i<end; i++) sum += nums[i];
return sum;
} int middle = start + (end-start)/2; AddTask subTask1 = new AddTask(start, middle);
AddTask subTask2 = new AddTask(middle, end);
subTask1.fork();
subTask2.fork(); return subTask1.join() + subTask2.join();
} }*/ public static void main(String[] args) throws IOException {
ForkJoinPool fjp = new ForkJoinPool();
AddTask task = new AddTask(0, nums.length);
fjp.execute(task);
//long result = task.join();
//System.out.println(result); System.in.read(); }
}
运行结果:

b.RescursiveTask 有返回值的递归任务
/**
* 对数组中所有数求和
* @author zhangqi
*
*/
public class T12_ForkJoinPool {
static int[] nums = new int[1000000];
static final int MAX_NUM = 50000;
static Random r = new Random(); static {
for(int i=0; i<nums.length; i++) {
nums[i] = r.nextInt(100);
} System.out.println(Arrays.stream(nums).sum()); //stream api
} /* static class AddTask extends RecursiveAction { int start, end; AddTask(int s, int e) {
start = s;
end = e;
} @Override
protected void compute() { if(end-start <= MAX_NUM) {
long sum = 0L;
for(int i=start; i<end; i++) sum += nums[i];
System.out.println("from:" + start + " to:" + end + " = " + sum);
} else { int middle = start + (end-start)/2; AddTask subTask1 = new AddTask(start, middle);
AddTask subTask2 = new AddTask(middle, end);
subTask1.fork();
subTask2.fork();
} } }*/ static class AddTask extends RecursiveTask<Long> { int start, end; AddTask(int s, int e) {
start = s;
end = e;
} @Override
protected Long compute() { if(end-start <= MAX_NUM) {
long sum = 0L;
for(int i=start; i<end; i++) sum += nums[i];
return sum;
} int middle = start + (end-start)/2; AddTask subTask1 = new AddTask(start, middle);
AddTask subTask2 = new AddTask(middle, end);
subTask1.fork();
subTask2.fork(); return subTask1.join() + subTask2.join();
} } public static void main(String[] args) throws IOException {
ForkJoinPool fjp = new ForkJoinPool();
AddTask task = new AddTask(0, nums.length);
fjp.execute(task);
long result = task.join();
System.out.println(result); //System.in.read(); }
}
运行结果:

补充:
ThreadPoolExecutor线程池执行器(自定义线程池,许多线程池的底层实现,ForkJoinPool不是由它实现)
Java高并发编程(四)的更多相关文章
- [ 高并发]Java高并发编程系列第二篇--线程同步
高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...
- java高并发编程(一)
读马士兵java高并发编程,引用他的代码,做个记录. 一.分析下面程序输出: /** * 分析一下这个程序的输出 * @author mashibing */ package yxxy.c_005; ...
- 关于Java高并发编程你需要知道的“升段攻略”
关于Java高并发编程你需要知道的"升段攻略" 基础 Thread对象调用start()方法包含的步骤 通过jvm告诉操作系统创建Thread 操作系统开辟内存并使用Windows ...
- Java高并发编程基础三大利器之CountDownLatch
引言 上一篇文章我们介绍了AQS的信号量Semaphore<Java高并发编程基础三大利器之Semaphore>,接下来应该轮到CountDownLatch了. 什么是CountDownL ...
- java高并发编程(三)
java高并发主要有三块知识点: synchronizer:同步器,在多个线程之间互相之间怎么进行通讯,同步等: 同步容器:jdk提供了同步性的容器,比如concurrentMap,concurren ...
- java高并发编程(四)高并发的一些容器
摘抄自马士兵java并发视频课程: 一.需求背景: 有N张火车票,每张票都有一个编号,同时有10个窗口对外售票, 请写一个模拟程序. 分析下面的程序可能会产生哪些问题?重复销售?超量销售? /** * ...
- java高并发编程(五)线程池
摘自马士兵java并发编程 一.认识Executor.ExecutorService.Callable.Executors /** * 认识Executor */ package yxxy.c_026 ...
- java高并发编程(二)
马士兵java并发编程的代码,照抄过来,做个记录. 一.分析下面面试题 /** * 曾经的面试题:(淘宝?) * 实现一个容器,提供两个方法,add,size * 写两个线程,线程1添加10个元素到容 ...
- java高并发编程基础之AQS
引言 曾经有一道比较比较经典的面试题"你能够说说java的并发包下面有哪些常见的类?"大多数人应该都可以说出 CountDownLatch.CyclicBarrier.Sempah ...
随机推荐
- Linux下自动清理超过指定大小文件的方法
由于线上业务用的squid,根据经验值如果长时间运行则缓存目录下的swap.state会慢慢变大,一旦超过60M,squid的性能就会急剧下降,因此需要定时去清理大于60M的swap.state文件. ...
- 深入Spring:自定义事务管理
转自: http://www.jianshu.com/p/5347a462b3a5 前言 上一篇文章讲了Spring的Aop,这里讲一下Spring的事务管理,Spring的事务管理是建立在Aop的基 ...
- (转)Java多线程学习(吐血超详细总结)
本文转自:http://blog.csdn.net/evankaka 写在前面的话:此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能 ...
- 初入Java后端之Servlet
初入Java后端之Servlet 后端 Servlet 什么是Servlet? Servlet实际上是一个按照Servlet规范写的Java类.是运行在Web服务端的Java应用程序.与Java程序 ...
- HDU 1576 A/B(欧几里德算法延伸)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1576 题目: Problem Description 要求(A/B)%9973,但由于A很大,我们只 ...
- SQL Server ——用 join on 连接多个表
select * from table1 inner join table2 on table1.id=table2.id 其实 INNER JOIN ……ON的语法格式可以概括为: FROM ((( ...
- 36.Linux驱动调试-根据oops定位错误代码行
1.当驱动有误时,比如,访问的内存地址是非法的,便会打印一大串的oops出来 1.1以LED驱动为例 将open()函数里的ioremap()屏蔽掉,直接使用物理地址的GPIOF,如下图所示: 1.2 ...
- SpringBoot整合Druid数据连接池
SpringBoot整合Druid数据连接池 Druid是什么? Druid是Alibaba开源的的数据库连接池.Druid能够提供强大的监控和扩展功能. 在哪里下载druid maven中央仓库: ...
- Hadoop windows 环境配置
下载 winutils 点击 这里下载 winutils 包,并解压缩. 此处解压缩后目录位置为 D:\software\hadoop2.6 配置环境变量 变量名 变量值 HADOOP_USER_NA ...
- python匿名函数lambda与switch的实现
1,lambda的语法跟es6的箭头函数差不多 >>> show=lambda x,y: x * y >>> show( 10, 20 ) 200 2,递归求阶乘 ...