创建线程的五种方式

1:继承Thread类创建线程

public class Thread01 extends Thread {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"子线程");
    }

    public static void main(String[] args) {
        // 当前是显示的名词是main主线程的名词
        System.out.println(Thread.currentThread().getName());
        Thread01 thread01 = new Thread01();
        Thread01 thread02 = new Thread01();
        Thread01 thread03 = new Thread01();

        thread01.start();
        thread02.start();
        thread03.start();
    }
}

2:实现Runnable接口实现多线程

public class ThreadRunnable implements Runnable{
    
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"子线程");
    }

    public static void main(String[] args) {
        // 当前是显示的名词是main主线程的名词
        System.out.println(Thread.currentThread().getName());
        Thread thread = new Thread(new ThreadRunnable());
        thread.start();
    }
}

3:使用Callable和Future创建线程

public class ThreadCallable implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        System.out.println(Thread.currentThread().getName()+"开始执行");
        Thread.sleep(3000);
        System.out.println(Thread.currentThread().getName()+"返回结果1");
        return 1;
    }
    
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ThreadCallable threadCallable = new ThreadCallable();
        FutureTask<Integer> integerFutureTask = new FutureTask<>(threadCallable);
        new Thread(integerFutureTask).start();
        Integer integer = integerFutureTask.get();
        System.out.println(Thread.currentThread().getName() + "," + integer);

    }

}

4:线程池创建线程

public class ThreadExecutor {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();

        executorService.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "子线程");
            }
        });
    }
    
}

5:使用spring的异步注解@Async

使用@Async进行异步的方式
1,在启动列或者能被启动类扫描到的配置类上标注@EnableAsync
2,在方法上加上注解@Async

在这里插入图片描述
这个是需要异步的方法,在方法上加注解
在这里插入图片描述
这里是调用sms方法的地方
在这里插入图片描述
最终结果:因为异步方法加了3秒延迟,所有是最后执行,并没有按照代码的先后循序执行

使用@Async注解会出现的问题,
1:无法保证事务一致性
2:因为默认最大线程和最大列队都是Interger.Max,如果在某一瞬间并发量突然变高,系统的负载会受不了。但是允许使用自定义线程池来替换默认线程池

自定义线程池实现@Async注解异步
首先自定义一个线程池

@Configuration
@EnableAsync
public class ThreadPoolConfig {

    /**
     * 每秒需要多少个线程处理?
     * tasks/(1/taskcost)
     */
    private int corePoolSize = 3;

    /**
     * 线程池维护线程的最大数量
     * (max(tasks)- queueCapacity)/(1/taskcost)
     */
    private int maxPoolSize = 3;

    /**
     * 缓存队列
     * (coreSizePool/taskcost)*responsetime
     */
    private int queueCapacity = 10;

    /**
     * 允许的空闲时间
     * 默认为60
     */
    private int keepAlive = 100;

    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        executor.setCorePoolSize(corePoolSize);
        // 设置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        // 设置队列容量
        executor.setQueueCapacity(queueCapacity);
        // 设置允许的空闲时间(秒)
        //executor.setKeepAliveSeconds(keepAlive);
        // 设置默认线程名称
        executor.setThreadNamePrefix("thread-");
        // 设置拒绝策略rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        return executor;
    }

}

然后指定线程池
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值