在业务开发中,有很多异步场景,为了节约时间或或者提高系统的吞吐量,要做一些异步任务,在Java中要实现异步通常都是Thread,开启一个线程Thread,开启线程有四种方式。
1、初始化线程池的4中方式
1)、继承Thread
2)、实现Runnable接口
lambda表达式使用要1.8版本以上,搭建maven项目需要设置maven的setting.xml文件,jdk是1.8以上
或者给maven添加配置,管理jdk版本是1.8
3)、实现Callable接口+FutureTask(可以拿到返回结果,可以处理异常)
4)、线程池
方法1
public class MyTest {
public static void main(String[] args) {
System.out.println("函数----开始");
//创建方法1
Thread1 thread1 = new Thread1();
thread1.start();//
System.out.println("函数----结束了");
//
}
}
public class Thread1 extends Thread{
//
@Override
public void run() {
System.out.println("当前线程:"+Thread.currentThread().getId());
int i=10/2;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("运行结果"+i);
super.run();
}
}
输出
函数----开始
函数----结束了
当前线程:12
运行结果5
方法二
public static void main(String[] args) {
System.out.println("函数----开始");
//
/* new Thread(里面new一个接口 把他的抽象方法全部写出来,这叫匿名内部类
new Runnable() {
@Override
public void run() {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果" + i);
}
}
);
*/
//创建方法2
Thread thread = new Thread(里面new一个接口 把他的抽象方法全部写出来,这叫匿名内部类
()-> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("运行结果" + i);
}
);
thread.start();
System.out.println("函数----结束了");
//
}
方式1和方式2 缺点:主进程无法获取线程的运算结果。
方式3:主进程可以获取线程的运算结果,但是不利于控制服务器中的线程资源。
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("函数----开始");
//创建方法3 有返回值
FutureTask<String> stringFutureTask = new FutureTask<>(() -> {
System.out.println("当前线程:"+Thread.currentThread().getId());
int i=10/2;
System.out.println("运行结果"+i);
return "ok"+i;
});
Thread thread = new Thread(stringFutureTask);
//线程执行
thread.start();
//获取返回值阻塞方法(运行到这就是阻塞的)
String s = stringFutureTask.get();
System.out.println("函数----结束了"+s);
}
结果:
函数----开始
当前线程:12
运行结果5
函数----结束了ok5
方式4:通过如下两种方式初始化线程池:
Excutors.newFiexedThreadPool(3);
// 或者
new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,TimeUnit unit, workQuene,threadFactory,handler);
通过线程池性能稳定,也可以获取执行结果,并捕获异常。但是,在业务复杂情况下,一个异步调用可能会依赖于另一个异步调用的执行结果。
线程测试
package com.atguigu.gulimall.search.thread;
/**
* @author: kaiyi
* @create: 2020-09-04 11:19
*/
public class ThreadTest {
public static void main(String[] args) {
System.out.println("main...start...");
/**
* 1)、继承Thread
* Thread01 thread = new Thread01();
* thread.start(); // 启动线程
*
* 2)、实现Runnable接口
* Runable01 runable01 = new Runable01()
* new Thread(runable01).start();
*
* 3)、实现Callable接口+FutureTask(可以拿到返回结果,可以处理异常)
* FutureTask<Integer> FutureTask = new FutureTask<>(new Callable01());
* new Thread(futureTask).start();
* // 阻塞等待整个线程执行完成,获取返回结果
* Integer integer = futureTask.get();
*
* 4)、线程池[ExecutorService]
* 给线程池直接提交任务。
* service.execute(new Runable01());
* 创建:
* ①、Excutors
* ②、new ThreadPoolExecutor
*
* Future:可以获取到异步结果
*/
Thread01 thread01 = new Thread01();
thread01.start(); // 启动线程
System.out.println("main...end...");
}
public static class Thread01 extends Thread{
@Override
public void run(){
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
}
}
}
执行结果打印:
main...start...
main...end...
当前线程:10
运行结果:5
Process finished with exit code 0
可以看到开启线程,进入了异步,主程序已经结束,线程才打印。