继昨天学习了线程池之后,今天学习了多线程内的锁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. 单元测试与Mockito

    1.什么是单元测试? 顾名思义单元测试就是对软件系统中最小的单元(函数.类)做测试,类似焊接电路板前对每个电容器(电子元器件)的测试.从软件测试分级来看,单元测试是最底层也是离程序员最近的一层,一般由 ...

  2. 算法题丨Remove Duplicates from Sorted Array

    描述 Given a sorted array, remove the duplicates in-place such that each element appear only once and ...

  3. 共创力咨询推出《静态代码分析(PCLint)高级实务培训》课程!

    [课程背景] C/C++语言的语法非常灵活性,尤其是指针及内存使用,这种灵活性使代码效率比较高,但同时也使得代码编写具有较大的随意性,另外C/C++编译器不进行强制类型检查,也不对数据边界和有效性进行 ...

  4. Windows系统下搭建Git本地代码库

    近由于工作需要,要把工作代码做一下版本管理.工作代码也不方便放到github上,也不想付费建私密库,公司也没几个人,所以就想着搭建一个本地Git版本库,来做版本管理.搭建过程如下. 系统环境:Dell ...

  5. webmagic 基本的方法

    WebMagic的结构分为Downloader.PageProcessor.Scheduler.Pipeline四大组件,并由Spider将它们彼此组织起来.这四大组件对应爬虫生命周期中的下载.处理. ...

  6. SQL Server 查看CPU情况

    --CPU相关视图 SELECT * FROM sys.dm_os_sys_info SELECT * FROM sys.dm_exec_sessions SELECT * FROM sys.sysp ...

  7. SpringBoot使用注解实现事务管理

    conttoller controller和普通的controller类一样, 不用改变 @RequestMapping(value = "/path/{id}", method ...

  8. 既然CPU同一时间只能执行一个线程,为什么存在并发问题

    一点小疑惑终于解开啦 1.CPU的时间是按时间片分的,而不是一个时间点,并发问题是由于CPU线程切换导致的. 现在假设有一段代码 if(i == 1) { i++; //断点1 system.out. ...

  9. Redis学习笔记(5)——Redis数据持久化

    出处http://www.cnblogs.com/xiaoxi/p/7065328.html 一.概述 Redis的强大性能很大程度上都是因为所有数据都是存储在内存中的,然而当Redis重启后,所有存 ...

  10. Python开发【内置模块篇】datetime

    获取当前日期和时间 >>> from datetime import datetime >>> now = datetime.now() >>> ...