1. 前言
且听风吟,御剑于心。——亚索
今天我们讲创建线程的“五种方式”,开干!非常简单!
2. 第一种 继承Thread类
继承Thread类,用..start()方式启动
//创建
static class MyThread extends Thread {
@Override
public void run() {
System.out.println("Hello MyThread!");
}
}
//启动
new MyThread().start();
3. 第二种 实现Runnable接口
实现Runnable接口,启动的时候还是需要new Thread对象
//创建
static class MyRun implements Runnable {
@Override
public void run() {
System.out.println("Hello MyThread!");
}
}
//启动
new Thread(new MyRun()).start();
4. 第三种 使用Lambda
使用Lambda 表达式!Lambda不懂的百度,简单来说就是简化代码。
//使用Lambda
new Thread(() -> System.out.println("Hello Lambda")).start();
//没使用Lambda表达式,含义和上面一样
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello Lambda");
}
}).start();
5. 第四种 使用线程池
下面的代码也是可以用Lambda表达式做优化的,只是我为了让大家看明白就这么写!
//线程池
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("Thread Pool!");
}
});
executorService.shutdown();
6. 第五种 Callable带返回值的任务执行
先来讲一下用Thread重写run方法是void,如果我们线程执行完事后想返回一个值就需要共享变量,或者静态变量,那我们就是不想用怎么办?好来了啊!用 Callable 可以指定泛型!使用还是用到线程池 返回类型是Future 是一个异步的,想要阻塞等待用.get()
//创建Callable
static class MyCall implements Callable<String> {
@Override
public String call() {
System.out.println("Hello Callable!");
return "success";
}
}
/*
* 带返回值的Callable
* Future 是一个异步非阻塞的,拿到请求自行处理!调用任务不等待!
* */
try {
Future<String> futureData = executorService.submit(new MyCall());
String s = futureData.get();//.get 是阻塞的会等着Future处理完
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
7. 第六种 这个是拓展,还是Callable,但是自己启动一个线程放Callable而不是使用线程池
new Thread 不可以直接传Callable,只能是Runnable。那JDK想个办法写个FutureTask,这个是可以放Callable,怎么做到的呢?看源码!
//自己创建一个线程放Callable
FutureTask<String> futureTask = new FutureTask<>(new MyCall());
new Thread(futureTask).start();
System.out.println(futureTask.get());
1 自己写了个RunnableFuture
2 多继承,继承一个Runnable一个Future 实现了run方法,那RunnableFuture既可以执行run也可以有自己的特性去装自己的返回值