java多线程使用与踩坑-配置多线程方法

实现:
1.线程池配置(配置完线程池后直接 @Async就可以异步调用注释的方法了)

@Configuration
@EnableAsync
public class AsyncConfiguration {

    @Bean("ceshiAsync")
    public Executor doSomethingExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程数:线程池创建时候初始化的线程数
        executor.setCorePoolSize(3);
        // 最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
        executor.setMaxPoolSize(4);
        // 缓冲队列:用来缓冲执行任务的队列
        executor.setQueueCapacity(10);
        // 允许线程的空闲时间60秒:当超过了核心线程之外的线程在空闲时间到达之后会被销毁
        executor.setKeepAliveSeconds(6);
        // 线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
        executor.setThreadNamePrefix("测试线程-");
        // 缓冲队列满了之后的拒绝策略:由调用线程处理(一般是主线程)
//        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
        executor.initialize();
        return executor;
    }

}

2.轮流打印的方法(此次是测试锁与多线程使用)( 两个方法完全一样,主要依靠list.notify(); list.wait();)

@Async("ceshiAsync")
    public void aaa(List<Integer> list) {
        System.out.println("线程A等待获取i锁");
        synchronized (list) {
            try {
                System.out.println("线程A获取了i锁");
                while (list.get(0)>-1){
                    log.info("线程A:"+list.get(0));
                    list.set(0,list.get(0)-1);
                    list.notify();
                    list.wait();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    @Async("ceshiAsync")
    public void bbb(List<Integer> list) {
        System.out.println("线程B等待获取i锁");
        synchronized (list) {
            try {
                System.out.println("线程B获取了i锁");
                while (list.get(0)>-1){
                    log.info("线程B:"+list.get(0));
                    list.set(0,list.get(0)-1);
                    list.notify();
                    list.wait();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

3.调用方法

List<Integer> list=new ArrayList<>();
    @Test
    @GetMapping(value = "ccc")
    public void ccc(){
        list.add(100);
        ceshiService.aaa(list);
        System.out.println("-----------");
        ceshiService.bbb(list);
    }

实现效果
在这里插入图片描述
在这里插入图片描述
踩坑

1.@Async注解未生效
原因:测试图方便把注解的方法直接写在方法,调用时直接用方法名调用,固注解未生效,这种写法会导致注解失效,例如事务的注解,但是与事务不同的时注入自身时记得添加 @Lazy注解,避免循环依赖。
在这里插入图片描述

2.current thread is not owner(当前线程不是所有者)错误
不要直接用Integer对象当锁,查询资料Integer内部的int值是不可改变的,估计是值改变时地址变了导致报这个错。

3.执行到一半报错
效果:在这里插入图片描述
原因:有些测试不适合用@Test注解,例如这里线程池出问题,事后想想这报错完全是理所应当的事情,亏我还在怀疑是notify方法提前把锁释放了导致wait执行时没锁了。罪过罪过

上一篇:将OpenCV与gdb驱动的IDE结合使用-用法


下一篇:云手机的数据安全有保障吗?