当前位置:   article > 正文

线程Thread,Runable,Callable与异步@Async_@async_call

@async_call

1.线程流程图

在这里插入图片描述
说明:
自定义的线程是由方法start()启动一个线程,然后执行run()方法,过程中可以通过sleep()方法进入睡眠延迟,通过interrupt()方法进行中断当前线程,并且在异常方法中return跳出当前线程,如果不return跳出,线程还会继续执行run()方法中的程序。获取当前线程名称:Thread.currentThread().getName()。

2.自定义一个线程的依赖结构图,可以看得出自定义的线程,都是线程对象Thread的子类,而Thread实现了Runbable的run方法。

在这里插入图片描述

3.自定义一个线程MyThread.java,线程传入参数的实现,是在子进程初始化时进行数据传入。

package com.springboot.thread.bean;

import java.text.SimpleDateFormat;
import java.util.Date;

//继承Thread类,重写run方法(其实Thread类本身也实现了Runnable接口)
public class MyThread extends Thread {
    //存储传入参数字段,在初始化子进程时,传入参数
    private String name;

    public  MyThread(String name){
       this.name = name;
    }

    @Override
    public void run()  {
            for (int i = 0; i < 100; i++) {
                 System.out.println(Thread.currentThread().getName());
                 System.out.println("多线程执行任务:是否可以传参数:"+this.name+"------------"+(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));
                //Thread.yield();
               try{
                    Thread.sleep(2000);
                   }catch (InterruptedException e) {
                    e.printStackTrace();
                    return;  //如果要异常时终止当前线程,一定要返回return;
                }
             }

    }

}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

3.1.controller层使用自定义的线程,并传入参数:

  @GetMapping("/startThread/{name}")
  public String startThread(@PathVariable String name)  throws InterruptedException{
         Thread myThread = new MyThread(name);
          myThread.start();
         // Thread.sleep(4000);
         // myThread.interrupt();
    return Thread.currentThread().getName();
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4.异步的实现。通过注释@EnableAsync和@Async来实现。

4.1.配置异步的配置文件AsyncTaskConfig .java。

说明:
主要实现AsyncConfigurer接口的getAsyncExecutor()方法获取一个执行器Executor 。

package com.springboot.thread.config;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
@Configuration
//开启异步支持
@EnableAsync
public class AsyncTaskConfig implements AsyncConfigurer {
  @Override
  public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    taskExecutor.setCorePoolSize(50);
    taskExecutor.setMaxPoolSize(100);
    taskExecutor.setQueueCapacity(100);
    taskExecutor.initialize();
    return taskExecutor;
  }

  @Override
  public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    return null;
  }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

4.2.定义异步方法ExecuteAsyncTask.java。

通过注释@Async来声明异步方法:

package com.springboot.thread.service;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class ExecuteAsyncTask {
    @Async
    public void executAsyncTask(Integer i){
    System.out.println("执行异步任务:----"+i);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

5.congroller层调用异步方法:

    @Autowired
    private ExecuteAsyncTask executeAsyncTask;
    @GetMapping("/startAsync")
    public String startAsync() {
        for (int i = 0; i < 1000; i++) {
            executeAsyncTask.executAsyncTask(i);
        }
        System.out.println("----程序运行完毕,不知道执行异步任务是否完毕----");
        return Thread.currentThread().getName();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

效果如下:
在这里插入图片描述

5.通过继承Callable接口的call()方法,自定义一个线程,可以返回结果给执行完线程后使用:

在这里插入图片描述

5.1.自定义一个Callable的实现类MyCallable.java

package com.springboot.thread.bean;

import java.util.concurrent.Callable;

public class MyCallable implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
    int result =0;
    for (int i = 0; i < 10; i++) {
      result =i;
    }
    System.out.println(Thread.currentThread().getName());
        return result;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

5.2controller层中使用自定义的callable实现类,需要通过FutureTask对象来获取返回的值,再传入到Thread线程中,生成一个子线程。

 @GetMapping("/startCallable")
    public String startCallable() throws InterruptedException, ExecutionException {
        for (int i = 0; i < 100; i++) {
            Callable<Integer> mycallable = new MyCallable();
            FutureTask<Integer> futureTask = new FutureTask<>(mycallable);
            new Thread(futureTask).start();
            System.out.println(Thread.currentThread().getName() + "------" + futureTask.get());
        }
        return Thread.currentThread().getName();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

6.线程池的实现。主要看Executors对象和ExecutorService对象:

6.1.Executors主要用来创建线程池,得到ExecutorService。

在这里插入图片描述

6.2.ExecutorService把Runable或者Callable对象通过提交到线程池里面,执行Executor的execute方法().

在这里插入图片描述

6.3.execute方法具体做了什么事情,如下:

说明:
把runable实例生成一个线程实例,并且执行start()的方法。
在这里插入图片描述

6.4.在controller层中使用线程池。

 @GetMapping("/submitExecutor")
    public String submitExecutor() {
        // 使用Executors工具类中的方法创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        MyRunnables myRunnables = new MyRunnables();
        // 为线程池中的线程分配任务,使用submit方法,传入的参数可以是Runnable的实现类,也可以是Callable的实现类
        for (int i = 0; i < 1000; i++) {
            executorService.submit(myRunnables);
            System.out.println(Thread.currentThread().getName() + "---"+i+"---");
        }
        // 关闭线程池
        // shutdown : 以一种平和的方式关闭线程池,在关闭线程池之前,会等待线程池中的所有的任务都结束,不在接受新任务
        // shutdownNow : 立即关闭线程池
        executorService.shutdown();
        return Thread.currentThread().getName();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

6.5.自定义的MyRunnables.java,如下:

package com.springboot.thread.bean;

public class MyRunnables implements Runnable {
    private int i =0;
    @Override
    public void run() {
        while (i<5000){
            System.out.println(Thread.currentThread().getName()+"----"+i++);
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

6.6.效果如下,同一个线程池里,使用不同的线程执行代码:
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/102615
推荐阅读
相关标签
  

闽ICP备14008679号