https://www.bilibili.com/video/BV1Wa4y1H7c7
多线程
并发是程序上的逻辑概念
并行是物理上的概念
java中,一切皆对象。想要创建一个子线程,也可以进行new。只不过和普通的堆上面的对象一样;然后当执行一个特殊的方法的时候(start)的时候,这个时候栈区就会多一个子线程(Runnable状态),当线程执行完毕销毁后,状态为Terminated
如何把任务交给线程呢?
1. 重新(override)Thread类的run方法
2. 实现Java.lang.Runnable接口,在创建Thread对象的时候传递到构造函数里面去
3. 使用FutureTask,在创建Thread对象的时候传递到构造函数里面去
public class TestThread{
public static void main(String[] args) {
Thread thread = new Thread() {
@Override
public void run() {
System.out.println("我是子线程");
}
};
thread.start();
System.out.println("main 结束");
}
}
//注意:让线程启动调用的是start方法,run只是普通方法,是子线程需要并行执行的内容
//那个线程调用run方法,run就会在那个线程上面执行
//这里的的run是方法重写
public class TestThread{
public static void main(String[] args) {
Thread thread = new Thread(() ->
System.out.println("我是子线程")
);
thread.start();
System.out.println("main 结束");
}
}
//如上:上面的实现runable采用了lambda表达式,因为这里是函数式接口
//这里采用的是run的接口封装,将runable作为参数给到了run
继续看:run方法统一都是没有参数,返回为void,不允许抛出异常
第三种方法可以有返回,也可以抛出异常【所以必然用到了线程间通信】
public class TestThread{
public static void main(String[] args) {
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("sub thread");
return "sub...";
}
};
FutureTask<String> task = new FutureTask<>(callable);
Thread thread = new Thread(task);
thread.start();
System.out.println("子线程启动");
try {
String s = task.get();
System.out.println("子线程返回值:"+s);
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main 结束");
}
}
//task.get的目的是获取子线程的返回值,发生了线程间通信。但是get是效率比较低的,因为是一直在等待子线程结束或者发生异常的
//A线程如果需要获取到B线程的返回结果,那么会问B或者问共同的朋友,或者找到关于B相关的信息
CompletableFuture
小工具类:
public class smallTollTest {
public static void sleepMills(long mills) {
try {
Thread.sleep(mills);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void printTimeAndThread(String tag){
String result = new StringJoiner("\t|\t")
.add(String.valueOf(System.currentTimeMillis()))
.add(String.valueOf(Thread.currentThread().getId()))
.add(Thread.currentThread().getName())
.add(tag)
.toString();
System.out.println(result);
}
}
场景补齐1:小白想吃饭,进入到了餐厅里面
public class TestThread{
public static void main(String[] args) {
smallTollTest.printTimeAndThread("小白进入餐厅");
smallTollTest.printTimeAndThread("小白点了一碗番茄炒蛋和一碗米饭");
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(
() -> {
smallTollTest.printTimeAndThread("厨师炒菜");
smallTollTest.sleepMills(200);
smallTollTest.printTimeAndThread("厨师打饭");
smallTollTest.sleepMills(100);
return "一碗番茄炒蛋和一碗米饭 做好了";
}
);
smallTollTest.printTimeAndThread("小白在打王者");
smallTollTest.printTimeAndThread(String.format("%s", "小白开吃",completableFuture.join()));
}
}
场景补齐2:厨师继续炒菜,但是打饭交给其他人
public class TestThread{
public static void main(String[] args) {
smallTollTest.printTimeAndThread("小白进入餐厅");
smallTollTest.printTimeAndThread("小白点了一碗番茄炒蛋和一碗米饭");
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(
() -> {
smallTollTest.printTimeAndThread("厨师炒菜");
smallTollTest.sleepMills(200);
return "一碗番茄炒蛋";
}
).thenCompose(dish -> CompletableFuture.supplyAsync(() -> {
smallTollTest.printTimeAndThread("服务员打饭");
smallTollTest.sleepMills(100);
return dish + "米饭";
}));
smallTollTest.printTimeAndThread("小白在打王者");
smallTollTest.printTimeAndThread(String.format("%s", "小白开吃",completableFuture.join()));
//thenCompose任务的结果是把上一个异步任务的结果,交给下一个异步任务。【上一个任务有结果后,下一个任务才会触发】
}
}
场景补齐3:厨师炒菜+服务员开始煮饭一起执行,然后服务员一起乘送到小白
public class TestThread{
public static void main(String[] args) {
smallTollTest.printTimeAndThread("小白进入餐厅");
smallTollTest.printTimeAndThread("小白点了一碗番茄炒蛋和一碗米饭");
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(
() -> {
smallTollTest.printTimeAndThread("厨师炒菜");
smallTollTest.sleepMills(200);
return "一碗番茄炒蛋";
}
).thenCombine(CompletableFuture.supplyAsync(() -> {
smallTollTest.printTimeAndThread("服务员蒸饭饭");
smallTollTest.sleepMills(300);
return "米饭";
}), (dish, rice) -> {
smallTollTest.printTimeAndThread("服务员打饭");
smallTollTest.sleepMills(100);
return String.format("%s + %s 好了",dish, rice);
});
smallTollTest.printTimeAndThread("小白在打王者");
smallTollTest.printTimeAndThread(String.format("%s", "小白开吃",completableFuture.join()));
}
}