异步处理springmvc的请求,关键字:@Async,CyclicBarrier,CountDownLatch

看到一个需求:得到一个请求,然后获得数据后响应给前台,并且把得到的数据添加到数据库中,需要异步处理.如果同步的话,需要等待写入数据库,响应前台的时间会变长.
使用到了springmvc的@Async异步处理.

使用方法是在mvc配置文件中加入<task:annotation-driven />
头文件加入xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd

然后在使用到的controller注入的业务类的方法上面,加上@Async

下面是我写的例子:

@Controller
public class Test {
    @Autowired
    private Service service;
    @RequestMapping("/index")
    public String index() throws InterruptedException {
        service.go();
        return "index";
    }
}

@Component
public class Service {
    @Async
    public void go() throws InterruptedException {
        for(int i=0;i<100000;i++) {
            Thread.sleep(1000);
            System.out.println("哈哈哈");
        }
    }
}

最终的效果是,接收请求后,代码会跳过异步业务直接响应到前台,异步业务会在前面业务执行完后自行后台执行.


那么我想到,如果需求是需要请求后台,后台同时处理多个业务,并且要将得到的数据响应到前台,如果单线程的话,时间会是所有处理时间的总和,等待响应时间比较长.
如果使用@Async这样异步处理的话,就不会等所有处理结果出来后,响应到前台.使用创建多个线程同时处理,多个线程也不会等全部执行完成后一起响应.
这时用到了CyclicBarrier类,它里面的await()方法,就起到了让多个线程互相等待,全部执行完成后再执行后面的代码.下面写的例子:

@Component
public class Service {
    public String b() {
        try {
            Thread.sleep(5000); //模拟执行业务
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "bbbb";
    }

    public String a() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "aaa";
    }
}
@Controller
public class Test {
    @Autowired
    private Service service;

    @RequestMapping("/index")
    public String index(Model model) {
        //这里构造的参数,代表了几个线程进入屏障,进行等待
        CyclicBarrier cyc = new CyclicBarrier(3);

        Thread th1 = new Thread() {
            @Override
            public void run() {
                String a = service.a();
                model.addAttribute("a", a);
                try {
                    cyc.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        };

        Thread th2 = new Thread() {
            @Override
            public void run() {
                String b = service.b();
                model.addAttribute("b", b);
                try {
                    cyc.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        };

        long t1 = System.currentTimeMillis();//计算处理时间
        th1.start();
        th2.start();

        try {
            cyc.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }

        long t2 = System.currentTimeMillis();
        model.addAttribute("c", t2 - t1);

        return "index";
    }
}
前台接收到的结果:
aaa
bbbb
5033  //这个时间就是其中一个需要处理最久的业务的时间

CyclicBarrier构造参数中设置的数量的所有的线程必须到齐后才能一起通过这个障碍,继续执行后面的代码.
如果使用CyclicBarrier(int parties,Runable barrierAction)这个构造,后面的实现Runable的代码,将在所有线程到齐后被执行.

CountDownLatch这个类的可以做到跟CyclicBarrier同样功能.
构造方法CountDownLatch(int count),参数是计数值.当用到方法countDown()时,计数减一.使用方法await()将挂起线程,等待计数器减到0后,继续执行其他线程.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值