文章目录
- 生产者消费者-阻塞队列版本
- Callable接口
生产者消费者-阻塞队列版本
关于上面的代码,多线程环境下,调用资源类,关键变量要加volatile,原子类变量不用加,因为源码里面的包装类加了,我们在这里使用就不用加。如果是想做适配性很好的代码设计,要适配所有的阻塞队列的子类,就不能在方法里确定,而是要让调用者把具体的实现传进来,也就是面向接口的编程。所谓的高手都是传接口,绝对不是传类!
关于这里的代码,写,要足够的抽象,也就是传接口,要查,要利用反射,把具体的类的实现记一下日志。
这个地方消费线程flag=false的行为,我不是很认同,消费线程取不到不应该停下吧,个人认为这个逻辑不对。
测试代码:
5s后叫停。
执行结果:
总结一下阻塞队列版本的线程通信:
Callable接口
多线程的方式:
两者的区别:1.runable接口没有返回值。但另一个是有的(适用于带返回值的线程工作流)。2.接口实现方法不一样,一个run,一个call、3
那么callable接口怎么在项目中使用呢?如果只用thread去接收callable接口该如何处理呢?目前thread只能接受runable接口。
如果一个类即实现了runable,也实现了callable,传这一个类就可以变相的适配了,这就是适配器模式的使用。
JDK给我们提供了,他就是futureTask接口。本身是runable接口的子类,传进去callable接口,就可以实现适配了。
实际使用:
运行结果:
如何获得callable的返回值呢?api提供了,如下:
这种用法在批次任务中,经常会出现。比如每一笔帐都要有返回值。
为什么callable会出现:并发,异步,导致callable出来了。
以前没有callable,编程的感觉就是一根签子通到底,冰糖葫芦串,顺序执行。如果节点占用时间过长,那就只能等着。
但是有了多线程之后,就可以用callable接口,把可以拆分的任务拆分出去并行执行,最后结果汇总。
多线程牛逼的不是锁,而是控制.
技巧:futureTask的get方法,建议放在最后执行。因为一旦get的那个任务还没执行完成,那么就会阻塞在这,所以get方法一般放在最后。
那么什么时候汇总呢?可以用自旋锁的思想,while一直去主动确认。
问题:如果一个futureTask被两个线程执行了2次,那么相关方法会如何执行?
结果是,只会执行一遍,因为一个计算过程算一遍就对了,不会算两遍。
总结:多个线程抢一个futureTask只算一次。要想多算,要有多个futureTask。
以上就是我们第三种获得线程的方式。runable,callable,futureTask。