面试官:线程有几种创建方式?
滴滴~ ( •̀ ω •́ )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 我们下期再见啦
ヾ( ̄▽ ̄)Bye~Bye~」
时间片,上下文,调度算法等知识点~
带你从CPU看到进程~(硬核)
Java中的锁居然有这么多!
终于来到 ConcurrentHashMap 了~
喜欢的小伙伴们可以关注交个朋友呀!谢谢支持!!😝
可以的话再麻烦您点个赞呀👍 谢谢!