4月11日java多线程4
继昨天学习了线程池之后,今天学习了多线程内的锁Lock。
定义方法:
ReentrantLock queueLock = new ReentrantLock(); //可重入锁
ReentrantReadWriteLock orderLock = new ReentrantReadWriteLock(); //可重入读写锁
每个锁都有个lock方法(上锁)和unlock方法(释放锁)
在写入锁的时候只能有一个线程,但是读取锁的时候可以线程一起共享锁里面的代码
今天还学习了信号量Semphore 自己定义最大可以同时运行多少线程
定义方法:
Semaphore placeSemaphore = new Semaphore(5);
使用acquire方法获得信号量 总信号量-1
使用release方法释放信号量 总信号量+1
附今日的代码:
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; public class LockExample { private static final ReentrantLock queueLock = new ReentrantLock(); //可重入锁
private static final ReentrantReadWriteLock orderLock = new ReentrantReadWriteLock(); //可重入读写锁 /**
* 有家奶茶店,点单有时需要排队
* 假设想买奶茶的人如果看到需要排队,就决定不买
* 又假设奶茶店有老板和多名员工,记单方式比较原始,只有一个订单本
* 老板负责写新订单,员工不断地查看订单本得到信息来制作奶茶,在老板写新订单时员工不能看订单本
* 多个员工可同时看订单本,在员工看时老板不能写新订单
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
//buyMilkTea();
handleOrder(); //需手动关闭
} public void tryToBuyMilkTea() throws InterruptedException {
boolean flag = true;
while(flag)
{
//判断queneLock现在是什么状态,如果是锁住的状态就返回false,如果是空闲状态则将它锁住返回true。
if (queueLock.tryLock()) {
//queueLock.lock();
//随机睡眠一段时间
long thinkingTime = (long) (Math.random() * 500);
Thread.sleep(thinkingTime);
System.out.println(Thread.currentThread().getName() + ": 来一杯珍珠奶茶,不要珍珠");
flag = false;
//将锁释放
queueLock.unlock();
} else {
//System.out.println(Thread.currentThread().getName() + ":" + queueLock.getQueueLength() + "人在排队");
System.out.println(Thread.currentThread().getName() + ": 再等等");
}
if(flag)
{
Thread.sleep(1000);
}
} } public void addOrder() throws InterruptedException {
//写入锁 锁住的情况下只能一个线程写
orderLock.writeLock().lock();
//睡眠一段时间
long writingTime = (long) (Math.random() * 1000);
Thread.sleep(writingTime);
System.out.println("老板新加一笔订单");
//释放锁
orderLock.writeLock().unlock();
} public void viewOrder() throws InterruptedException {
//读取锁 锁住的情况下可以多个线程一起共享
orderLock.readLock().lock();
//睡眠一段时间
long readingTime = (long) (Math.random() * 500);
Thread.sleep(readingTime);
System.out.println(Thread.currentThread().getName() + ": 查看订单本");
//释放锁
orderLock.readLock().unlock(); } //买奶茶方法
public static void buyMilkTea() throws InterruptedException {
LockExample lockExample = new LockExample();
//定义线程数
int STUDENTS_CNT = 10;
//建立线程
Thread[] students = new Thread[STUDENTS_CNT];
for (int i = 0; i < STUDENTS_CNT; i++) {
//给每个线程完成初始化
students[i] = new Thread(new Runnable() { @Override
public void run() {
try {
//随机睡眠一段时间
long walkingTime = (long) (Math.random() * 1000);
Thread.sleep(walkingTime);
//尝试现在是否能够买奶茶
lockExample.tryToBuyMilkTea();
} catch(InterruptedException e) {
System.out.println(e.getMessage());
}
} }
);
//让所有线程开始工作
students[i].start();
} for (int i = 0; i < STUDENTS_CNT; i++)
//等待所有线程结束
students[i].join(); } public static void handleOrder() throws InterruptedException {
LockExample lockExample = new LockExample(); //创建了一个老板写的线程类并且完成了初始化。
Thread boss = new Thread(new Runnable() { @Override
public void run() {
while (true) {
try {
//添加订单
lockExample.addOrder();
//随机睡眠一段时间
long waitingTime = (long) (Math.random() * 1000);
Thread.sleep(waitingTime);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
});
//老板线程开始
boss.start();
//定义员工线程数
int workerCnt = 3;
//创建员工线程
Thread[] workers = new Thread[workerCnt];
for (int i = 0; i < workerCnt; i++)
{
//给每个员工线程初始化
workers[i] = new Thread(new Runnable() { @Override
public void run() {
while (true) {
try {
//查看订单
lockExample.viewOrder();
//睡眠一段时间
long workingTime = (long) (Math.random() * 5000);
Thread.sleep(workingTime);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
} });
//员工线程开始工作
workers[i].start();
} }
}
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
//定义了5个车位
private final Semaphore placeSemaphore = new Semaphore(5);
public boolean parking() throws InterruptedException {
//如果此时Semaphore信号量不为0就会获取一个信号量返回true并且信号量-1,如果信号量为0的话则返回false
if (placeSemaphore.tryAcquire()) {
System.out.println(Thread.currentThread().getName() + ": 停车成功");
return true;
} else {
System.out.println(Thread.currentThread().getName() + ": 没有空位");
return false;
}
}
public void leaving() throws InterruptedException {
//释放掉一个信号量,信号量+1
placeSemaphore.release();
System.out.println(Thread.currentThread().getName() + ": 开走");
}
/**
* 现有一地下车库,共有车位5个,由10辆车需要停放,每次停放时,去申请信号量
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
//定义总共要停车的数量
int tryToParkCnt = 10;
SemaphoreExample semaphoreExample = new SemaphoreExample();
//创建要停车的数量的线程
Thread[] parkers = new Thread[tryToParkCnt];
for (int i = 0; i < tryToParkCnt; i++) {
//将每个线程进行初始化
parkers[i] = new Thread(new Runnable() {
//这是视频里面的源代码,我在运行之后发现结果和我想象中的有点不同,因为有的车没有停到车位,不是等待之后再停车,而是直接没有停车了。
//原因是不管if里面返回true或是false都只会执行一次,如果是false的话就只输出了一个没有空位,然后线程就结束了。
//所以我在if判断的外面加了一个while死循环,当if为true,车成功的停车然后离开车位之后break退出循环。
// @Override
// public void run() {
// try {
// long randomTime = (long) (Math.random() * 1000);
// Thread.sleep(randomTime);
// if (semaphoreExample.parking()) {
// long parkingTime = (long) (Math.random() * 1200);
// Thread.sleep(parkingTime);
// semaphoreExample.leaving();
// }
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
@Override
public void run() {
try {
exit:
while(true)
{
//睡眠一段时间
long randomTime = (long) (Math.random() * 1000);
Thread.sleep(randomTime);
//尝试进行停车,如果停车成功会返回true
if (semaphoreExample.parking()) {
//睡眠一段时间,然后调用离开方法
long parkingTime = (long) (Math.random() * 1200);
Thread.sleep(parkingTime);
semaphoreExample.leaving();
break exit;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//让每个线程开始工作
parkers[i].start();
}
for (int i = 0; i < tryToParkCnt; i++) {
//等待每个线程结束
parkers[i].join();
}
}
}
4月11日java多线程4的更多相关文章
- 4月10日java多线程3
在之前我学习了java中的Thread 来实现多线程,今日我学习了ThreadGroup.Executor框架.ForkJoin框架.Executor 和ForkJoin都可以直接定义线程池,可以根据 ...
- IT培训行业变革大会,7月11日启程!
自上世纪八十年代PC时代起,IT行业走过了以2G移动网络和宽带网络.PC终端为主要载体,软件产品.应用软件和门户网站为特征产品的PC互联网时代. 以3/4G移动和高速宽带和移动终端为主要载体,移动支付 ...
- 4月11日 python学习总结 对象与类
1.类的定义 #类的定义 class 类名: 属性='xxx' def __init__(self): self.name='enon' self.age=18 def other_func: pas ...
- 【视频】k8s套娃开发调试dapr应用 - 在6月11日【开源云原生开发者日】上的演示
这篇博客是在2022年6月11日的[开源云原生]大会上的演讲中的演示部分.k8s集群套娃(嵌套)是指在一个k8s的pod中运行另外一个k8s集群,这想法看上去很疯狂,实际上非常实用. k8s集群套娃( ...
- Yoshua Bengio 2016年5月11日在Twitter Boston的演讲PPT
Yoshua Bengio最新演讲:Attention 让深度学习取得巨大成功(46ppt) Yoshua Bengio,电脑科学家,毕业于麦吉尔大学,在MIT和AT&T贝尔实验室做过博士后研 ...
- 2015年12月28日 Java基础系列(六)流
2015年12月28日 Java基础系列(六)流2015年12月28日 Java基础系列(六)流2015年12月28日 Java基础系列(六)流
- 8月11日嵌入式Linux开发免费项目体验邀您参与
嵌入式Linux开发免费项目体验开课啦~~我们特意邀请到粤嵌金牌讲师和技术专家,为大家带来精彩有趣的嵌入式公开课,涉及到嵌入式学习.研发的方方面面.课堂中我们能体验到的不仅仅是最新资讯.技术体验,还有 ...
- 2016年12月11日 星期日 --出埃及记 Exodus 21:6
2016年12月11日 星期日 --出埃及记 Exodus 21:6 then his master must take him before the judges. He shall take hi ...
- 2016年11月11日 星期五 --出埃及记 Exodus 20:2
2016年11月11日 星期五 --出埃及记 Exodus 20:2 "I am the LORD your God, who brought you out of Egypt, out o ...
随机推荐
- Dynamics CRM图表高级话题:创建跨实体的图表
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复147或者20150728可方便获取本文,同时可以在第一时间得到我发布的最新的博文信息,follow me! 制作图表你会发现,在界面上只能选 ...
- Netty学习笔记(六) 简单的聊天室功能之WebSocket客户端开发实例
在之前的Netty相关学习笔记中,学习了如何去实现聊天室的服务段,这里我们来实现聊天室的客户端,聊天室的客户端使用的是Html5和WebSocket实现,下面我们继续学习. 创建客户端 接着第五个笔记 ...
- Python使用Plotly绘图工具,绘制气泡图
今天来讲讲如何使用Python 绘图工具,Plotly来绘制气泡图. 气泡图的实现方法类似散点图的实现.修改散点图中点的大小,就变成气泡图. 实现代码如下: import plotly as py i ...
- Vue一个案例引发「动画」的使用总结
项目开发中动画有着很重要的作用,而且也是用到的地方非常多,例如:鼠标的进入离开,弹窗效果,组件的显示隐藏,列表的切换等等,可以说我们网页上的动画无处不在,也有人说了,这些东西也可以不使用动画. 对,你 ...
- Python HTML解析器BeautifulSoup(爬虫解析器)
BeautifulSoup简介 我们知道,Python拥有出色的内置HTML解析器模块——HTMLParser,然而还有一个功能更为强大的HTML或XML解析工具——BeautifulSoup(美味的 ...
- 关于Python, ftplib模块中的cwd()进入含中文目录失败的问题
使用Python的ftplib模块连接ftp服务器时, 使用cwd()连接含中文的目录, 报错 : UnicodeEncodeError: 'latin-1' codec can't encode c ...
- java反射(java.lang.reflect)---java.lang.reflect.Modifier中状态码
1. 详情请看jvm(虚拟机)规范 java.lang.reflect.Modifier public static final int ABSTRACT 1024 public static fin ...
- it's time to change myself now (2018.10.31)
自16年从新屋熊职校毕业,入职深圳某厂从事云存储两年半了.两年半的时间很快,快的感觉一生都会飞快,两年多一直很忙,忙的几乎忘了自己是否正向改变过. 正向改变,or 积极改变,今年十一回家,与几个好友小 ...
- 关于c#(vs)dategridview控件继承不能修改的问题
问题描述:前几天写个小项目的时候,用到了一个父窗体,然后继承过来的dategridview控件不管是属性还是事件都不能修改. 如下图所示: 然后我就在网上找资料,但是有关这个问题的资源甚少,或许是我不 ...
- Jquery自动补全插件的使用
1.引入css和js <script src="js/jquery-ui.min.js"></script> <link href="cs ...