多线程操作中为什么使用while而不是if来做判断状态是否就绪
在多线程操作中,我们常常会遇到需要先判断信号量状态是否就绪,然后执行后续操作的场景。这里对状态的判断使用的是while而不是单线程下常用的if。
以下示例展示了一个简单的生产者-消费者模型:当队列满的时候,阻塞set;当队列为空的时候,阻塞get操作。
public class EventStorage {
private int maxSize;
private List<Date> storage;
public EventStorage(){
maxSize=10;
storage=new LinkedList<>();
}
public synchronized void set(){
while (storage.size()==maxSize){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
storage.offer(new Date());
System.out.printf("Set: %d",storage.size());
notifyAll();
}
public synchronized void get(){
while (storage.size()==0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("Get: %d: %s",storage.
size(),((LinkedList<?>)storage).poll());
notifyAll();
}
}
public class Producer implements Runnable {
private EventStorage storage;
public Producer(EventStorage storage){
this.storage=storage;
}
@Override
public void run() {
for (int i=0; i<100; i++){
storage.set();
}
}
}
public class Consumer implements Runnable {
private EventStorage storage;
public Consumer(EventStorage storage){
this.storage=storage;
}
@Override
public void run() {
for (int i=0; i<100; i++){
storage.get();
}
}
}
public class Main {
public static void main(String[] args) {
EventStorage storage=new EventStorage();
Producer producer=new Producer(storage);
Thread thread1=new Thread(producer);
Consumer consumer=new Consumer(storage);
Thread thread2=new Thread(consumer);
thread1.start();
thread2.start();
}
}
在set中使用了
while (storage.size()==maxSize){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
在get中使用了
while (storage.size()==0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
原因:
在线程中notify或者notifyAll会唤醒一个或多个线程,当线程被唤醒后,被唤醒的线程继续执行阻塞后的操作。
这里分析一下get操纵: 当某个线程得到锁时storage为空,此时它应该wait,下次被唤醒时(任意线程调用notify),storage可能还是空的。因为有可能其他线程清空了storage。如果此时用的是if它将不再判断storage是否为空,直接继续,这样就引起了错误。但如果用while则每次被唤醒时都会先检查storage是否为空再继续,这样才是正确的操作;生产也是同一个道理。
多线程操作中为什么使用while而不是if来做判断状态是否就绪的更多相关文章
- 为什么使用 SLF4J 而不是 Log4J 来做 Java 日志
转自:为什么使用 SLF4J 而不是 Log4J 来做 Java 日志 英文原文:Why use SLF4J over Log4J for logging in Java 每个Java开发人员都知道日 ...
- java多线程为什么要用while而不是if
对于java多线程的wait()方法,我们在jdk1.6的说明文档里可以看到这样一段话 从上面的截图,我们可以看出,在使用wait方法时,需要使用while循环来判断条件十分满足,而不是if,那么我们 ...
- MySQL用B+树(而不是B树)做索引的原因
众所周知,MySQL的索引使用了B+树的数据结构.那么为什么不用B树呢? 先看一下B树和B+树的区别. B树 维基百科对B树的定义为"在计算机科学中,B树(B-tree)是一种树状数据结构, ...
- Java中request请求之 - 带文件上传的form表单
常用系统开发中总免不了显示图片,保存一些文件资料等操作. 这些操作的背后,就是程序员最熟悉的 enctype="multipart/form-data"类型的表单. 说起file类 ...
- 多线程(五) java的线程锁
在多线程中,每个线程的执行顺序,是无法预测不可控制的,那么在对数据进行读写的时候便存在由于读写顺序多乱而造成数据混乱错误的可能性.那么如何控制,每个线程对于数据的读写顺序呢?这里就涉及到线程锁. 什么 ...
- Python 多进程 多线程 协程 I/O多路复用
引言 在学习Python多进程.多线程之前,先脑补一下如下场景: 说有这么一道题:小红烧水需要10分钟,拖地需要5分钟,洗菜需要5分钟,如果一样一样去干,就是简单的加法,全部做完,需要20分钟:但是, ...
- 第13章 C#中的多线程
章多线程 13.1 线程概述 计算机的操作系统多采用多任务和分时设计.多任务是指在一个操作系统中开以同时运行多个程序.例如,可以在使用QQ聊天的同时听音乐,即有多个独立的任务,每个任务对应一个进程,每 ...
- Java中的多线程你只要看这一篇就够了
学习Java的同学注意了!!! 学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:279558494 我们一起学Java! 引 如果对什么是线程.什么是进程仍存有疑惑, ...
- Java面试题整理一(侧重多线程并发)
1..是否可以在static环境中访问非static变量? 答:static变量在Java中是属于类的,它在所有的实例中的值是一样的.当类被Java虚拟机载入的时候,会对static变量进行初始化.如 ...
随机推荐
- 装有Win7系统的电脑在局域网不能共享的解决方案
Win7系统的网络功能比XP有了进一步的增强,使用起来也相对清晰.但是由于做了很多表面优化的工作,使得底层的网络设置对于习惯了XP系统的人来说变得很不适应,其中局域网组建就是一个很大的问题.默认安装系 ...
- SDWebImage 原理及使用
这个类库提供一个UIImageView类别以支持加载来自网络的远程图片.具有缓存管理.异步下载.同一个URL下载次数控制和优化等特征. SDWebImage 加载图片的流程 入口 setImageWi ...
- C#泛型的性能优势
我写东西一向追求短小精悍,就不放代码去验证的,只说结论,并会与Java泛型做对比.有不对之处还望指出. 泛型作为一个在C#2.0中就引入的特性,也是C#的重要特性之一,我经常看到有人讨论泛型带来的便捷 ...
- HDU2054JAVA
(包括2016级新生)除了校赛,还有什么途径可以申请加入ACM校队? A == B ? Time Limit: 1000/1000 MS (Java/Others) Memory Limit: ...
- iOS 网络编程:socket
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- 父页面iframe自动适应子页面的宽高度
<script type="text/javascript"> function load(){ parent.document.getElementById(&quo ...
- HDU 5637 Transform
题意: 有两种变换: 1. 改变此数二进制的某一位(1变成0 或者 0变成1) 2. 让它与给出的n个数当中的任意一个做异或运算 给你两个数s, t,求从s到t最少要经过几步变换,一共m组查询思路: ...
- # Day04-Android
Day04-Android 标签(空格分隔): andrroid 1.制作界面 2.在写Activity. Logcat LayoutInflate把Xml转换纯成View的工具. 自定义吐司 Lay ...
- 如何在OpenWRT环境下做开发
1.搭建开发环境 首先,在执行make menuconfig后,会出现下图: 其中,图中红框部分是我定制路由器的系统版本,大家可以根据不同的路由器进行不同的选择:绿框部分表示我们需要编译一个SDK开发 ...
- Linux上安装KDE, Gnome和VNC
安装所需环境:需要至少256m的可用内存(128也可以不过有点卡)CentOS或类似OS(Debian的话改成apt-get应该也可以) 1,安装KDE 1 yum install kdepim 或安 ...