在业务开发中,有很多异步场景,为了节约时间或或者提高系统的吞吐量,要做一些异步任务,在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

可以看到开启线程,进入了异步,主程序已经结束,线程才打印。