最近看了咕泡学视频教程,这里算是做一个记录。
package study.java5;
/**
* @Auther: zhw
* @Date: 2018/10/28 11:16
* @Description: 1.5多线程方式1
*/
public class ThreadDemo {
public static void main(String[] args) {
Demo1 demo1 = new Demo1();
demo1.start();
}
}
class Demo1 extends Thread
{
@Override
public void run() {
System.out.println("线程开始执行");
}
}
package study.java5;
/**
* @Auther: zhw
* @Date: 2018/10/28 12:29
* @Description: //TODO
*/
public class RunnableDemo {
public static void main(String[] args) {
Demo2 demo2 =new Demo2();
Thread thread = new Thread(demo2);
thread.start();
}
}
class Demo2 implements Runnable{
@Override
public void run() {
System.out.println("线程开始执行");
}
}
1.5总结:
1、缺少线程池的管理
2、想获取线程执行的结果非常麻烦
这个可以算是线程的管理,其中包含各种线程服务
ExecutorService:最常见的执行者。生命周期
ScheduledExecutorService:带有任务调度的执行者
ThreadFactory:线程工厂,用于创建新线程
public class ExecutorsExecutorService {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
Future future = executorService.submit(new Callable(){
@Override
public String call() throws Exception {
return "first executorService";
}
});
//do other thing
String result = "";
try {
result = future.get();
}catch (Exception e) {
e.printStackTrace();
}
System.out.println(result);
}
}
如上面例子,创建了一个数量为2的线程池,返回了ExecutorServie,ExecutorServie调用了submit方法产生了一个Future结果.
区分Callable和Future
Callable:是源头,是任务,是产生结果的。
Future:Future是用于获取结果的。由于Callable的调用是异步的,也就是说结果不知道什么时候产生,也就是这个单词的意思“未来”,这是个未来结果。
详解Future
除了submit还有invokeAll(也就是批量)、invokeAny(这个有点用)、execute,看jdk源码或者名字都很好理解
其他服务就不介绍了。
在1.5中已经出现了线程池、线程管理、获取线程的执行结果,已经很方便了,所以jdk1.5是个经典。
缺点:
多个线程之间交互需要提高(但是还是不影响1.5是经典)
背景:ForkJoinPool的优势在于,可以充分利用多cpu,多核cpu的优势,把一个任务拆分成多个“小任务”,把多个“小任务”放到多个处理器核心上并行执行;当多个“小任务”执行完成之后,再将这些执行结果合并起来即可。这种思想值得学习。
这里特别推荐一篇文章,写的非常好=====>精彩博文
主要有两个类:RecursiveAction和RecursiveTask
下面演示一个打印任务
public static void main(String[] args) throws Exception{
PrintTask task = new PrintTask(0, 100);
//创建实例,并执行分割任务
ForkJoinPool pool = new ForkJoinPool();
pool.submit(task);
//线程阻塞,等待所有任务完成
pool.shutdown();
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
System.out.println("线程池已经关闭");
}
class PrintTask extends RecursiveAction{
private static final int THRESHOLD = 10; //最多只能打印50个数
private int start;
private int end;
public PrintTask(int start, int end) {
super();
this.start = start;
this.end = end;
}
@Override
protected void compute() {
if(end - start < THRESHOLD){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i=start;i
public static void main(String[] args) throws Exception {
int[] arr = new int[100];
Random random = new Random();
int total =0;
//方式一、初始化100个数组元素,并且通过单线程计算出总和
for(int i=0,len = arr.length;i future = pool.submit(task); //提交分解的SumTask 任务
System.out.println("多线程执行结果:"+future.get());//这里会阻塞线程,等待所有子线程结束。
pool.shutdown(); //关闭线程池
}
class SumTask extends RecursiveTask{
private static final int THRESHOLD = 20; //每个小任务 最多只累加20个数
private int arry[];
private int start;
private int end;
/**
* Creates a new instance of SumTask.
* 累加从start到end的arry数组
* @param arry
* @param start
* @param end
*/
public SumTask(int[] arry, int start, int end) {
super();
this.arry = arry;
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
int sum =0;
//当end与start之间的差小于threshold时,开始进行实际的累加
if(end - start
对于累加等操作jdk1.8提供了其他的类:LongAccumulator.
解释几个概念:
中文解释: 开始一个有序的关闭,在关闭过程中以前提交的任务还是会被执行,
但是不会 接受新的提交的任务。
英文解释:
/**
* Possibly initiates an orderly shutdown in which previously
* submitted tasks are executed, but no new tasks will be
* accepted. Invocation has no effect on execution state if this
* is the {@link #commonPool()}, and no additional effect if
* already shut down. Tasks that are in the process of being
* submitted concurrently during the course of this method may or
* may not be rejected.
*/
大致和shutdown相同,但是它会取消现有的和未执行的任务,非常符合方法名字的定义
英文解释:
/**
* Possibly attempts to cancel and/or stop all tasks, and reject
* all subsequently submitted tasks.
它会阻塞当前线程,除非发生下面任何一种情况
1、在发出shutdown请求后,所有的任务都完成
2、出现timeout的情况
3、当前线程被中断。
所以在ForkJoinPool中经常看到这样的代码
//发出关闭线程请求,但是已提交的不会终止
pool.shutdown();
//等待子任务执行完成,如果子任务执行完成,线程会关闭
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
或者
pool.shutdown();
while (!pool.awaitTermination(1, TimeUnit.SECONDS)) {
System.out.println("子线程还没有执行完成");
}
System.out.println("子线程池执行完成,线程池也关闭了");