前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >学习使用Lock+Conditionk编写三个经典多线程例子

学习使用Lock+Conditionk编写三个经典多线程例子

作者头像
我是攻城师
发布2018-08-03 10:59:34
3360
发布2018-08-03 10:59:34
举报
文章被收录于专栏:我是攻城师我是攻城师

前言

在jdk5之后的高级并发包里面Lock接口可以替换原来jvm内置的锁synchronized关键字,同理使用Condition接口的await,signal,signalAll方法分别可以替换原来的协作方式wait,notify,notifyAll。

关于Condition接口

相比原来的Object提供的协作方式,新的Condition接口则是更加以面相对象的方式展现,它跟Lock接口绑定,新的定义可以在一个锁上声明多个条件量,它的一个模板写法如下:

代码语言:javascript
复制
private Lock lock=new ReentrantLock();

    Condition full=lock.newCondition();

    Condition empty=lock.newCondition();

相比原来的wait,notify,notifyAll方法,Condition接口还提供了额外的两个功能:

代码语言:javascript
复制
boolean awaitUntil(Date deadline)
 void awaitUninterruptibly()

第一个是提供了可以wait到具体某一个时间后,自动唤醒自己。

第二个是提供了wait不可打断的方法。

另外一个与比之前协作强大的地方,就是同一个锁上可以声明多个独立的条件量,举个例子之前的生产者消费者协作模式,生产者和消费者共用一个信号量的问题是,执行notify方法默认是随机唤醒一个线程,如果生产者和消费者共享一个信号量,那么底层相当于维护一个wait队列,那么消费者唤醒生产者线程的时候,有可能还是唤醒的消费者线程,所以这一点相当于是不可控的,粒度太粗,所以Condition接口就是为解决这个问题出现的,允许我们在一个锁对象上声明多个信号量,分别维护不同的等待队列,这样以来,如果 需要唤醒生产者线程,那么直接使用其对应的信号量即可,这样以来就能保证唤醒的一定是生产者线程。

例子一(多线程卖票)

功能点分析:

使用Lock接口实现模拟火车站多个窗口卖票的功能,这里票是共享资源,同一张票只能有一个线程可以卖出,如果票卖完就告诉用户无票。此外为了避免某一个线程卖的太快,把所有的票都垄断,导致有的窗口可能永远也卖不了票,所以这里需要注意合理的控制cpu资源,不能让一个线程一直抢用。

4个线程(窗口)卖10张票的结果输出如下:

代码语言:javascript
复制
窗口1 卖出了票id=10
窗口2 卖出了票id=9
窗口4 卖出了票id=8
窗口3 卖出了票id=7
窗口1 卖出了票id=6
窗口1 卖出了票id=5
窗口2 卖出了票id=4
窗口4 卖出了票id=3
窗口3 卖出了票id=2
窗口1 卖出了票id=1
窗口3 票已经售完,谢谢光临!
窗口2 票已经售完,谢谢光临!
窗口4 票已经售完,谢谢光临!
窗口1 票已经售完,谢谢光临!

例子二(模拟生产者消费者)

功能点分析:

这里面有2个线程,一个生产者一个消费者,这里假设队列大小是10,如果队列满了,生产者就要等待消费者消费,如果队列空了,那么消费者就要等待生产,这里面也可以控制生产和消费的速度:

代码语言:javascript
复制
生产者放入一条数据:87
生产者放入一条数据:51
生产者放入一条数据:86
生产者放入一条数据:94
生产者放入一条数据:71
生产者放入一条数据:8
生产者放入一条数据:10
生产者放入一条数据:57
生产者放入一条数据:72
生产者放入一条数据:61
Thread-0 队列满了,生产者开始阻塞 
消费者消费一条数据:87
消费者消费一条数据:51
消费者消费一条数据:86
消费者消费一条数据:94
消费者消费一条数据:71

例子三(两个线程交替打印奇数和偶数)

功能点分析:

这里面需要一个数字累加器,如果+1后是奇数那么奇数就应该打印数据,同时偶数线程阻塞,当奇数打印完毕后,要+1更新奇数器,同时唤醒偶数线程,偶数的逻辑与奇数线程类似,如果是偶数就打印,否则就进入等待状态,同时+1更新计数器,然后唤醒奇数线程。

代码语言:javascript
复制
even偶数线程阻塞
odd线程 打印 1
odd奇数线程阻塞
even线程 打印 2
even偶数线程阻塞
odd线程 打印 3
odd奇数线程阻塞
even线程 打印 4
even偶数线程阻塞
odd线程 打印 5
odd奇数线程阻塞
even线程 打印 6
even偶数线程阻塞
odd线程 打印 7
odd奇数线程阻塞
even线程 打印 8

总结

本文主要了在Lock接口里面的条件量的使用以及它与jdk5之前的线程协作方式相比的优点,同时本文又给出了是三个在线程里面经典的例子运行结果的输出,这里由于篇幅原因代码不再贴出,感兴趣的朋友可以到我的github上下载完整例子代码。

github地址:

https://github.com/qindongliang/Java-Note

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-07-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 我是攻城师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 关于Condition接口
  • 例子一(多线程卖票)
  • 例子二(模拟生产者消费者)
  • 例子三(两个线程交替打印奇数和偶数)
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档