滴滴~ ( •̀ ω •́ )y
4ye 今天来和大家分享下 线程的创建方式 啦😝
面试官:线程有几种创建方式?
这个也太简单了叭~ 😝
继承 Thread 类
步骤如下:
- 创建一个类继承
Thread - 重写
run方法 - 调用
Thread类的start方法
类图~
代码如下
public class MyThread extends Thread{
@Override
public void run() {
System.out.println(this.getClass().getSimpleName());
}
public static void main(String[] args) {
MyThread myThread=new MyThread();
myThread.start();
}
}
实现 Runnable 接口
步骤如下:
- 创建一个类实现
Runnable - 重写
run方法 - 将该类传递到
Thread类的构造函数中 - 调用
Thread类的start方法
代码如下
public class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println(this.getClass().getSimpleName());
}
public static void main(String[] args) {
Thread myRunable=new Thread(new MyRunnable());
myRunable.start();
}
}
实现 Callable 接口,结合 Future 类获取返回值
特点:可以获取线程的执行结果
步骤如下:
- 创建一个类实现
Callable - 重写
call方法 - 创建
FutureTask类,将该类传递到FutureTask类的构造函数中 - 将
FutureTask类传递到Thread类的构造函数中 - 调用
Thread类的start方法 - 调用
FutureTask类的get方法获取线程执行结果
FutureTask 类不知道大家熟不熟悉~ ,这是它的类图😋
可以发现它也是实现了这个 Runnable 接口 ,对比上面发现大家都实现了这个 Runnable 接口 。
然后传参到 Thread 类的构造器中,然后再去调用 start 方法去启动线程~🐷
代码如下
/**
* @author Java4ye
* @date 2021/4/15 6:58
* @微信公众号: Java4ye
* @GitHub https://github.com/RyzeYang
* @博客 https://blog.csdn.net/weixin_40251892
*/
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return this.getClass().getSimpleName();
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<String> futureTask=new FutureTask<>(new MyCallable());
Thread thread = new Thread(futureTask);
thread.start();
System.out.println(futureTask.get());
}
}
通过线程池创建线程
线程池常见创建的方式有 5 种,具体的讲到 线程池 篇再展开~ 😝
这里的例子使用 固定线程数量的线程池 : newFixedThreadPool
步骤如下:
- 使用 Executors 创建线程池
- 创建一个实现
Runnable或者Callable接口的类 - 针对 没有 返回值的,有
execute方法 - 针对 有 返回值的有 , 有
submit方法
代码如下
execute 方式
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.execute(new MyRunnable());
executor.shutdown();
submit 方式
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<String> future = executor.submit(new MyCallable());
System.out.println(future.get());
executor.shutdown();
有几种创建方式呢
嘿嘿 让我数一数 👉 一共有 四 种
事情真的这么简单吗~
当我无意间打开这个 Thread 的源码时,发现它居然说 有两种方式 , 就是前两种方式
虽然官方文档里说两种,但是 咱们和面试官说的时候肯定是说四种呀~ 😋
多多益善 哈哈哈哈 ~
看到这个表情包表示还没结束呢 U•ェ•*U 哈哈哈
还可以和 面试官 说说下面这种异步处理结果的 ,Future 增强版!CompletableFuture (上面的 FutureTask 是阻塞版~)
CompletableFuture
为什么又来了一个 Future 呢?
主要是因为用 Future 获得异步执行结果时,要调用 阻塞方法 get() 或者轮询 isDone() 判断是否为true,这两种方法都会导致主线程被 阻塞 ,和我们想的异步不一样~ (我们需要它再帮我们处理下异步线程的执行结果呀😝)
所以在 JDK1.8 新引入了该类 CompletableFuture ,它实现了 Future 接口 ,又通过 CompletionStage 接口扩展了功能,增加了异步事件,实现异步处理线程执行完的结果,不用我们通过 Future 的阻塞方式去手动处理。
除了异步执行结果 外,它还可以 异步处理异常 ,具体看下面的例子😄
类图:
部分方法介绍
supplyAsync 表示创建带返回值的异步任务
runAsync 表示创建无返回值的异步任务
thenAccept 处理返回值,无返回结果
exceptionally 出现异常时,执行 exceptionally 中的回调方法。
正常例子
public class MyCompletableFuture {
public static void main(String[] args) {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Java4ye");
completableFuture.thenAccept(System.out::println);
completableFuture.exceptionally(throwable -> {
System.out.println(throwable.getMessage());
return throwable.getMessage();
});
}
}
异常例子
public class MyCompletableFuture {
public static void main(String[] args) {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> ""+1/0);
completableFuture.thenAccept(System.out::println);
completableFuture.exceptionally(throwable -> {
System.out.println(throwable.getMessage());
return throwable.getMessage();
});
}
}
嘿嘿 后面有机会再单独写一个介绍 CompletableFuture 的 ,里面还有很多方法 😝
总感觉这样结束也太干巴巴了 , 最后再和大家分享一道题 , 嘿嘿 你觉得答案是啥呢?
new Thread(()->{
System.out.println("A");
}){
@Override
public void run() {
System.out.println("B");
}
}.start();
嘿嘿 这里的答案是 B , 看着花里胡哨的,其实是子类重写了父类的 run 方法 ~
回顾
目前 多线程 篇章 已经和小伙伴们分享了 这三个知识点啦 冲冲冲!😝
我是 4ye 我们下期再见啦 ヾ( ̄▽ ̄)ByeBye
欢迎关注,交个朋友呀!! ( •̀ ω •́ )y
作者简介 :Java4ye 在补更技术文的程序员4ye呀,很高兴认识你!!😝
关注公众号: Java4ye 欢迎关注博主滴个人公众号~ 这里给你准备了一系列的学习资源啦,还有各种插件,软件哦 😋
让我们开始这一场意外的相遇吧!~
欢迎留言!谢谢支持!ヾ(≧▽≦*)o