多线程中wait、notify理解
实在惭愧,java开发多年,多线程运用一直不多,该知识点理解也不够,不怎么会用。赶上使用多线程 生产者、消费者模式,学习下该知识点。
synchronized 获取锁
wait 阻塞本线程,释放对象锁。该线程会在该代码处阻塞,不往下执行。
notify 释放对象锁,通知其他被阻塞的线程可以被唤醒。
Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。
IllegalMonitorStateException异常发生是由于程序员没有注意notify(),notify(),wait()方法的使用条件,没有真正理解线程同步机制。如果当前的线程不是此对象锁的所有者,却调用该对象的notify(),notify(),wait()方法时抛出该异常。个人暂时理解为若线程没有持有任何锁,而调用这几个方法,会出现该异常。
package socket; public class Producer2 extends Thread { public class Producer extends Thread { private Share shared; private int number; public Producer(Share s, int number) { shared = s; this.number = number; } public void run() { for (int i = 0; i < 10; i++) { System.out.println("[00]"); shared.put(i); System.out.println("生产者" + this.number + " 输出的数据为:" + i); try { sleep((int) (Math.random() * 100));//这里一定要加,否则(注释掉sleep代码)消费者可能会暂时取不到cpu控制权,而没办法打印出信息。而此时消费者get()方法中已经执行notify方法,导致生产者被唤醒,继续生产执行put(),给人误导没有消费。实际已经消费而只是未打印而已。 } catch (InterruptedException e) { } System.out.println("[000]"); } } } // 共享资源对象 public class Share { private int contents; private boolean available = false; public synchronized int get() { System.out.println("[1]"); if (available == false) { try { System.out.println("[2]"); wait(); System.out.println("[3]"); } catch (InterruptedException e) { } } available = false; System.out.println("[4]"); notify();// 通知其他使用该对象的线程,你们可以在适当的时间被唤醒了。只要我锁一释放(synchronized方法体执行完),其他线程就有被唤醒的可能,就有可能把锁抢过去执行了。 System.out.println("[5]"); return contents; } public synchronized void put(int value) { System.out.println("[6]"); if (available == true) { try { System.out.println("[7]"); wait();// 我不使用该对象了,本线程睡觉了,现在是其他对象被唤醒的时机,你们可以在被wait的地方继续执行了 System.out.println("[8]"); } catch (InterruptedException e) { } } available = true; System.out.println("[9]"); notify();//这里也要加,原因是,用于唤醒其他线程,不加的话,在本线程睡觉后,消费者线程不被唤醒,生产者线程唤醒其他线程的notify方法没有机会执行,那生产者线程会一直睡大觉了。 System.out.println("[10]"); contents = value; } } // 消费者程序 public class Consumer extends Thread { private Share shared; private int number; public Consumer(Share s, int number) { shared = s; this.number = number; } public void run() { int value = 0; for (int i = 0; i < 10; i++) { System.out.println("[11]"); value = shared.get(); System.out.println("消费者" + this.number + " 得到的数据为:" + value); } } } // 主程序 public static void main(String[] args) { Producer2 test = new Producer2(); Share s = test.new Share(); Producer p = test.new Producer(s, 1); Consumer c = test.new Consumer(s, 1); p.start(); try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } c.start(); } }
多线程中wait、notify理解的更多相关文章
- Java多线程中wait, notify and notifyAll的使用
本文为翻译文章,原文地址:http://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example 在Java的Obje ...
- java多线程中wait/notify/sleep/join/yield方法以及多线程的六种状态
刚开始学线程的时候也是被这几个方法搞的云里雾里的,尤其是一开始看的毕老师的视频,老师一直在强调执行权和执行资格,看的有点懵逼,当然不是说毕老师讲的不好,就是自己有点没听明白,后来复习看了一些其他的博客 ...
- python多线程中join()的理解
在 Python 的多线程编程中,经常碰到 thread.join()这样的代码.那么今天咱们用实际代码来解释一下 join 函数的作用. 第一,当一个进程启动之后,会默认产生一个主线程,因为线程是程 ...
- 多线程中Object的wait(),notify()和Condition的wait()和singal()对锁的关联
通常将共享资源的操作放置在Sysnchronized定义的区域内,这样当其他线程也获取到这个锁时,必须的等待锁被释放时才能进入该区域.Object为任意一个对象,每个对象都存在一个标志位,并具有两个值 ...
- 多线程中的"断点"续传《notify()和wait()》
眼下在做一个项目.关于软件管理与下载的,预计项目提交日期定在6月9号.项目做了有20天了,可是在一个功能上卡住了.在这个项目中有一个功能----APK的下载须要实现. 相信大家都玩过非常多关于下载AP ...
- Java多线程中线程间的通信
一.使用while方式来实现线程之间的通信 package com.ietree.multithread.sync; import java.util.ArrayList; import java.u ...
- python 多线程中的同步锁 Lock Rlock Semaphore Event Conditio
摘要:在使用多线程的应用下,如何保证线程安全,以及线程之间的同步,或者访问共享变量等问题是十分棘手的问题,也是使用多线程下面临的问题,如果处理不好,会带来较严重的后果,使用python多线程中提供Lo ...
- Java多线程中的常用方法
本文将带你讲诉Java多线程中的常用方法 Java多线程中的常用方法有如下几个 start,run,sleep,wait,notify,notifyAll,join,isAlive,current ...
- c#语言-多线程中的锁系统(一)
介绍 平常在多线程开发中,总避免不了线程同步.本篇就对net多线程中的锁系统做个简单描述. 目录 一:lock.Monitor 1:基础. 2: 作用域. ...
- 如何在多线程中调用winform窗体控件
由于 Windows 窗体控件本质上不是线程安全的.因此如果有两个或多个线程适度操作某一控件的状态(set value),则可能会迫使该控件进入一种不一致的状态.还可能出现其他与线程相关的 bug,包 ...
随机推荐
- java是用utf-16be编码方式编的。中文和英文都是两个字节
- java jdk1.7后 sting intern()方法与之前的区别
public static void main(String[] args) { String s1 = new StringBuilder("计算机").append(" ...
- codeforces 710C C. Magic Odd Square(构造)
题目链接: C. Magic Odd Square Find an n × n matrix with different numbers from 1 to n2, so the sum in ea ...
- 【二叉查找树】04根据升序数组构造二叉查找树【Convert Sorted Array to Binary Search Tree】
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 给定一个升序的数组,把他转换成一个 ...
- ACM学习历程—UESTC 1217 The Battle of Chibi(递推 && 树状数组)(2015CCPC C)
题目链接:http://acm.uestc.edu.cn/#/problem/show/1217 题目大意就是求一个序列里面长度为m的递增子序列的个数. 首先可以列出一个递推式p(len, i) = ...
- Anthem.NET 的回调流程图
下面用一个最简单的 anthem:Button 回调作为例子,理清回调过程中执行函数的次序.代码如下: <%@ Page Language="C#" AutoEventWir ...
- Ubuntu下安装软件
在ubuntu当中,安装应用程序有三种方法,分别是:apt-get,dpkg安装deb和make install安装源码包三种. apt-get方法 使用apt-get install来安装应用程序算 ...
- spring扩展点之二:spring中关于bean初始化、销毁等使用汇总,ApplicationContextAware将ApplicationContext注入
<spring扩展点之二:spring中关于bean初始化.销毁等使用汇总,ApplicationContextAware将ApplicationContext注入> <spring ...
- GCC提供的几个內建函数
参考 https://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Other-Builtins.html#Other-Builtins https://en.wikipe ...
- uboot搬移部分和重定位部分的代码分析
来看一下搬移部分和重定位部分的代码: relocate: /* 把U-BOOT重新定位到RAM*/ //r0=0; adr r0, _start /* r0是代码的当前位置*/ ld ...