在多线程操作中,我们常常会遇到需要先判断信号量状态是否就绪,然后执行后续操作的场景。这里对状态的判断使用的是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来做判断状态是否就绪的更多相关文章

  1. 为什么使用 SLF4J 而不是 Log4J 来做 Java 日志

    转自:为什么使用 SLF4J 而不是 Log4J 来做 Java 日志 英文原文:Why use SLF4J over Log4J for logging in Java 每个Java开发人员都知道日 ...

  2. java多线程为什么要用while而不是if

    对于java多线程的wait()方法,我们在jdk1.6的说明文档里可以看到这样一段话 从上面的截图,我们可以看出,在使用wait方法时,需要使用while循环来判断条件十分满足,而不是if,那么我们 ...

  3. MySQL用B+树(而不是B树)做索引的原因

    众所周知,MySQL的索引使用了B+树的数据结构.那么为什么不用B树呢? 先看一下B树和B+树的区别. B树 维基百科对B树的定义为"在计算机科学中,B树(B-tree)是一种树状数据结构, ...

  4. Java中request请求之 - 带文件上传的form表单

    常用系统开发中总免不了显示图片,保存一些文件资料等操作. 这些操作的背后,就是程序员最熟悉的 enctype="multipart/form-data"类型的表单. 说起file类 ...

  5. 多线程(五) java的线程锁

    在多线程中,每个线程的执行顺序,是无法预测不可控制的,那么在对数据进行读写的时候便存在由于读写顺序多乱而造成数据混乱错误的可能性.那么如何控制,每个线程对于数据的读写顺序呢?这里就涉及到线程锁. 什么 ...

  6. Python 多进程 多线程 协程 I/O多路复用

    引言 在学习Python多进程.多线程之前,先脑补一下如下场景: 说有这么一道题:小红烧水需要10分钟,拖地需要5分钟,洗菜需要5分钟,如果一样一样去干,就是简单的加法,全部做完,需要20分钟:但是, ...

  7. 第13章 C#中的多线程

    章多线程 13.1 线程概述 计算机的操作系统多采用多任务和分时设计.多任务是指在一个操作系统中开以同时运行多个程序.例如,可以在使用QQ聊天的同时听音乐,即有多个独立的任务,每个任务对应一个进程,每 ...

  8. Java中的多线程你只要看这一篇就够了

    学习Java的同学注意了!!! 学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:279558494 我们一起学Java! 引 如果对什么是线程.什么是进程仍存有疑惑, ...

  9. Java面试题整理一(侧重多线程并发)

    1..是否可以在static环境中访问非static变量? 答:static变量在Java中是属于类的,它在所有的实例中的值是一样的.当类被Java虚拟机载入的时候,会对static变量进行初始化.如 ...

随机推荐

  1. UIWindow详解

    UIScreen(屏幕),UIWindow(窗口),UIView(视图)是iOS的几个基本界面元素.其中UIWindow(窗口)和UIView(视图)是为iPhone应用程序构造用户界面的可视组件.U ...

  2. 256MB小内存MySQL配置优化

    [client] port = 3306 socket = /var/run/mysqld/mysqld.sock [mysqld_safe] socket = /var/run/mysqld/mys ...

  3. CSS常见问题及兼容性

    CSS常见问题 1 (IE6,7)H5标签兼容 解决方法1:(只显示核心代码) 1<script>  ; ; ;                    ;;;};;;;;;;;       ...

  4. 可扩展多线程异步Socket服务器框架EMTASS 2.0 续

    转载自Csdn:http://blog.csdn.net/hulihui/article/details/3158613 (原创文章,转载请注明来源:http://blog.csdn.net/huli ...

  5. javascript-图片横向无缝隙滚动(可在服务器运行)

    前两次弄'图片横向滚动'javascript,在本地上运行得很美,可是一上到我们学校后台的服务器,就有很多问题,这个算是行的了. css代码: <style type="text/cs ...

  6. Orcale安装完成后 em管理、性能无法登陆 报:没有找到主机

    先在我的电脑环境变量中加入oracle_sid=orcl 在Orcale主目录中查找emd.properties 文件修改(时间格式) agentTZRegion=GMT agentTZRegion= ...

  7. js EasyUI前台 价格=数量*单价联动的实现

    废话,不多说,,效果图如下:

  8. list集合中指定字段去重

    在开发中,有时会需要指定字段去重,以下为实现方法: 假设有个房地产权的类,其中宗地代码ZDDM值重复,而我们在前端页面显示时,只需要一条数据,因为公共字段都一样: IEqualityComparer需 ...

  9. Linux/Unix下设置定时任务

    Unix系统提供了cron和at命令,使系统和用户可以定时运行一定的程序,而不需手工启动. 使用cron用于周期性的执行一个命令,为了使用它,必须编辑crontab文件.系统缺省的/etc/cront ...

  10. OC多文件开发介绍

    OC多文件开发介绍: 1.为什么要使用多文件? 在工作中,通常把不同的类放到不同的文件中,每个类的声明和实现分开,声明写在.h头文件中,实现写在相应的.m文件中去,类名是什么,文件名的前缀就是什么.假 ...