继昨天学习了线程池之后,今天学习了多线程内的锁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的更多相关文章

  1. 4月10日java多线程3

    在之前我学习了java中的Thread 来实现多线程,今日我学习了ThreadGroup.Executor框架.ForkJoin框架.Executor 和ForkJoin都可以直接定义线程池,可以根据 ...

  2. IT培训行业变革大会,7月11日启程!

    自上世纪八十年代PC时代起,IT行业走过了以2G移动网络和宽带网络.PC终端为主要载体,软件产品.应用软件和门户网站为特征产品的PC互联网时代. 以3/4G移动和高速宽带和移动终端为主要载体,移动支付 ...

  3. 4月11日 python学习总结 对象与类

    1.类的定义 #类的定义 class 类名: 属性='xxx' def __init__(self): self.name='enon' self.age=18 def other_func: pas ...

  4. 【视频】k8s套娃开发调试dapr应用 - 在6月11日【开源云原生开发者日】上的演示

    这篇博客是在2022年6月11日的[开源云原生]大会上的演讲中的演示部分.k8s集群套娃(嵌套)是指在一个k8s的pod中运行另外一个k8s集群,这想法看上去很疯狂,实际上非常实用. k8s集群套娃( ...

  5. Yoshua Bengio 2016年5月11日在Twitter Boston的演讲PPT

    Yoshua Bengio最新演讲:Attention 让深度学习取得巨大成功(46ppt) Yoshua Bengio,电脑科学家,毕业于麦吉尔大学,在MIT和AT&T贝尔实验室做过博士后研 ...

  6. 2015年12月28日 Java基础系列(六)流

    2015年12月28日 Java基础系列(六)流2015年12月28日 Java基础系列(六)流2015年12月28日 Java基础系列(六)流

  7. 8月11日嵌入式Linux开发免费项目体验邀您参与

    嵌入式Linux开发免费项目体验开课啦~~我们特意邀请到粤嵌金牌讲师和技术专家,为大家带来精彩有趣的嵌入式公开课,涉及到嵌入式学习.研发的方方面面.课堂中我们能体验到的不仅仅是最新资讯.技术体验,还有 ...

  8. 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 ...

  9. 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 ...

随机推荐

  1. 从.Net到Java学习第五篇——Spring Boot &&Profile &&Swagger2

    从.Net到Java学习系列目录 刚学java不久,我有个疑问,为何用到的各种java开源jar包许多都是阿里巴巴的开源项目,为何几乎很少见百度和腾讯?不是说好的BAT吗? Spring Boot 的 ...

  2. django入门与实践 - 关于升级到django 3.7,三种模板超链接配置(编辑中)

    第一种方法: 在myblog/urls.py模块中: from django.contrib import admin from django.urls import path, include ur ...

  3. 软件 利用 win+R 快速启动(无需添加环境变量)

    前言:以 "Typora" 软件 为例 ,无需添加环境变量,实现键盘快速启动 第一步 找到 为知笔记的快捷方式 打开文件位置 鼠标右击该软件的桌面快捷方式 复制该软件的快捷方式 第 ...

  4. CSS优先级的及其衡量标准CSS权重

    一.背景 CSS有三大特性:层叠性.继承性.优先级. 而我们在给CSS定义样式的时候,经常出现两个及以上的规则应用在同一元素上,单该元素最终在浏览器呈现的效果是应用的哪个规则呢?这就要考虑优先级的问题 ...

  5. BCP SQL导出EXCEL常见问题及解决方法;数据导出存储过程

    一.‘xp_cmdshell’的启用 SQL Server阻止了对组件‘xp_cmdshell’的过程‘sys.xp_cmdshell’的访问.因为此组件已作为此服务嚣安全配置的一部分而被关 闭.系统 ...

  6. Saltstack_使用指南07_远程执行-执行模块

    1. 主机规划 远程执行教程文档 https://docs.saltstack.com/en/latest/topics/tutorials/modules.html 所有模块文档 https://d ...

  7. 二、Windows Server 2016 AD 组织单位、组、用户的创建

    简介: 组织单位简称OU,OU是(Organizational Unit)的缩写,组织单位是可以将用户.组.计算机和组织单位放入其中的容器.是可以指派组策略设置或委派管理权限的最小作用域或单元. 建立 ...

  8. 初学python列表

    首先我定义了一个列表 a = [2,3,3,5,6,7,9] 我想对列表a 的每个值都加一,哈,脑子里顿时闪过一道光 ①首先我想到的是用for 循环来进行加一,即以下代码 a = [2,3,3,5,6 ...

  9. admin组件

    Django 提供了基于 web 的管理工具. Django 自动管理工具是 django.contrib 的一部分.你可以在项目的 settings.py 中的 INSTALLED_APPS 看到它 ...

  10. 专治编译器编辑器vscode中文乱码输出 win10 配置系统默认utf-8编码

    VS Code输出会出现乱码,很多人都遇到过.这是因为VS Code内部用的是utf-8编码,cmd/Powershell是gbk编码.直接编译,会把“你好”输出成“浣犲ソ”.如果把cmd的活动代码页 ...