一、为什么多线程很重要?
- 硬件方面:摩尔定律的失效,多核的出现
- 软件方面:高并发系统
摩尔定律是由英特尔(Intel)创始人之一戈登·摩尔(Gordon Moore)提出来的。其内容为:当价格不变时,集成电路上可容纳的晶体管数目,约每隔18个月便会增加一倍,性能也将提升一倍。换言之,每一美元所能买到的电脑性能,将每隔18个月翻两倍以上。这一定律揭示了信息技术进步的速度。
二、进程、线程、管程
进程:资源分配的基本单位
线程:cpu调度的基本单位
管程:Monitor(锁)
三、用户线程和守护线程
1.thread.setDaemon()设置守护线程
2.用户线程结束,守护线程自动结束
public class YonghuAndShouhu {
public static void main(String[] args) {
Thread A =new Thread(()->{
System.out.println("这是守护线程");
while (true){//保证这个方法不停
}
},"A");
A.setDaemon(true);
A.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("这是main线程");
}
}
四、FutureTask的get()方法引起阻塞的解决办法
FutureTask实现了RunnableFuture,RunnableFuture继承了Future和Runnable接口
使用FutureTask的get()方法时可能会引起阻塞(本程序两秒后才返回值)
public class FutureTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> vFutureTask = new FutureTask<>(() -> {
Thread.sleep(2000);
return 1024;
});
new Thread(vFutureTask,"a").start();
System.out.println(vFutureTask.get());//get()会引起阻塞
System.out.println("main");
}
}
解决get()方法阻塞的方法有那些?
get得到的是返回值,这个返回值要在其他方法里用到
① futureTask 返回值出来被调用后才出main(出现阻塞)
② CompletableFuture 在等返回值时mian已经出来,等返回值出来再被调用
- 将get()方法放到最后 (不见不散)
- 用有参get()方法:.get(1, TimeUnit.SECONDS) (过时不候)
- 轮询 :
public class FutureTest {
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
FutureTask<Integer> vFutureTask = new FutureTask<>(() -> {
Thread.sleep(2000);
return 1024;
});
new Thread(vFutureTask,"a").start();
//
//轮询
while(true){
if (vFutureTask.isDone()){
System.out.println(vFutureTask.get());
break;
}else{
System.out.println("不要催l");
}
}
System.out.println("main");
}
}
4. CompletableFuture
五、CompletableFuture(对Future的加强)
1.四个静态方法的使用
public class CompletableFutureTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,20,1L, TimeUnit.SECONDS,new LinkedBlockingDeque<>(50), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
//无返回值 默认线程池
CompletableFuture<Void> voidCompletableFuture1 = CompletableFuture.runAsync(() -> {
System.out.println(Thread.currentThread().getName() + "1");
});
System.out.println(voidCompletableFuture1.get());
//无返回值 自定义线程池
CompletableFuture<Void> voidCompletableFuture2 = CompletableFuture.runAsync(() -> {
System.out.println(Thread.currentThread().getName() + "2");
},threadPoolExecutor);
System.out.println(voidCompletableFuture2.get());
//有返回值 默认线程池
CompletableFuture<Object> objectCompletableFuture3 = new CompletableFuture<>().supplyAsync(()->{
System.out.println(Thread.currentThread().getName() + "3");
return 3;
});
System.out.println(objectCompletableFuture3.get());
//有返回值 自定义线程池
CompletableFuture<Object> objectCompletableFuture4 = new CompletableFuture<>().supplyAsync(()->{
System.out.println(Thread.currentThread().getName() + "4");
return 4;
},threadPoolExecutor);
System.out.println(objectCompletableFuture4.get());
threadPoolExecutor.shutdown();
解决阻塞
public class CompletableFutureTest2 {
public static void main(String[] args) {
CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
}).thenApply((f)->{
return f+1;
}).whenComplete((v,e)->{
if (e == null){
System.out.println("result"+v);
}
}).exceptionally((e)->{
e.printStackTrace();
return null;
});
System.out.println("main");
//如果主线程关闭,那么默认的线程池会关闭,让主线程多跑5秒,让上面的result跑出来
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2.常用方法
-
得出处理结果
-
对计算结果进行处理
-
对计算结果进行消费
4. 对计算速度进行选用
applyToEither()
假设玩家A玩家B玩游戏,谁先出来谁赢
public class applyToEitherTest {
public static void main(String[] args) {
System.out.println(CompletableFuture.supplyAsync(() -> {
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
}).applyToEither(CompletableFuture.supplyAsync(() -> {
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 2;
}), r -> {
return r;
}).join());
}
}
- 对计算结果进行合并
thenCombine()
public class applyToEitherTest {
public static void main(String[] args) {
System.out.println(CompletableFuture.supplyAsync(() -> {
return 1;
}).thenCombine(CompletableFuture.supplyAsync(() -> {
return 2;
}), (r1,r2) -> {
return r1+r2;
}).join());
}
}