- 浏览: 674870 次
- 性别:
- 来自: 深圳
最新评论
-
fingerplay:
请问一下,第一份,逻辑树,就是代码里可以操纵的,例如更改lay ...
UIView与CALayer -
ok_lyc:
分享到哪里去了
iPhoneUIFont各种字体 -
lliiqiang:
我的个人理解:wait方法是在java虚拟机层面上在获取对象锁 ...
JAVA多线程同步wait、notify、synchronized -
milixw:
谢谢分享,就在找这个
iphone 推送通知 java 实现 -
wsqwsq000:
你的log4j包不行,上网搜一下:log4j-1.2.16.j ...
iphone 推送通知 java 实现
1 wait方法:
该方法属于Object的方法,wait方法的作用是使得当前调用wait方法所在部分(代码块)的线程停止执行,并释放当前获得的调用wait所在的代码块的锁,并在其他线程调用notify或者notifyAll方法时恢复到竞争锁状态(一旦获得锁就恢复执行)。
调用wait方法需要注意几点:
第一点:wait被调用的时候必须在拥有锁(即synchronized修饰的)的代码块中。
第二点:恢复执行后,从wait的下一条语句开始执行,因而wait方法总是应当在while循环中调用,以免出现恢复执行后继续执行的条件不满足却继续执行的情况。
第三点:若wait方法参数中带时间,则除了notify和notifyAll被调用能激活处于wait状态(等待状态)的线程进入锁竞争外,在其他线程中interrupt它或者参数时间到了之后,该线程也将被激活到竞争状态。
第四点:wait方法被调用的线程必须获得之前执行到wait时释放掉的锁重新获得才能够恢复执行。
2 notify方法和notifyAll方法:
notify方法通知调用了wait方法,但是尚未激活的一个线程进入线程调度队列(即进入锁竞争),注意不是立即执行。并且具体是哪一个线程不能保证。另外一点就是被唤醒的这个线程一定是在等待wait所释放的锁。
notifyAll方法则唤醒所有调用了wait方法,尚未激活的进程进入竞争队列。
3 synchronized关键字:
第一点:synchronized用来标识一个普通方法时,表示一个线程要执行该方法,必须取得该方法所在的对象的锁。
第二点:synchronized用来标识一个静态方法时,表示一个线程要执行该方法,必须获得该方法所在的类的类锁。
第三点:synchronized修饰一个代码块。类似这样:synchronized(obj) { //code.... }。表示一个线程要执行该代码块,必须获得obj的锁。这样做的目的是减小锁的粒度,保证当不同块所需的锁不冲突时不用对整个对象加锁。利用零长度的byte数组对象做obj非常经济。
4 atomic action(原子操作):
在JAVA中,以下两点操作是原子操作。但是c和c++中并不如此。
第一点:对引用变量和除了long和double之外的原始数据类型变量进行读写。
第二点:对所有声明为volatile的变量(包括long和double)的读写。
另外:在java.util.concurrent和java.util.concurrent.atomic包中提供了一些不依赖于同步机制的线程安全的类和方法。
该方法属于Object的方法,wait方法的作用是使得当前调用wait方法所在部分(代码块)的线程停止执行,并释放当前获得的调用wait所在的代码块的锁,并在其他线程调用notify或者notifyAll方法时恢复到竞争锁状态(一旦获得锁就恢复执行)。
调用wait方法需要注意几点:
第一点:wait被调用的时候必须在拥有锁(即synchronized修饰的)的代码块中。
第二点:恢复执行后,从wait的下一条语句开始执行,因而wait方法总是应当在while循环中调用,以免出现恢复执行后继续执行的条件不满足却继续执行的情况。
第三点:若wait方法参数中带时间,则除了notify和notifyAll被调用能激活处于wait状态(等待状态)的线程进入锁竞争外,在其他线程中interrupt它或者参数时间到了之后,该线程也将被激活到竞争状态。
第四点:wait方法被调用的线程必须获得之前执行到wait时释放掉的锁重新获得才能够恢复执行。
2 notify方法和notifyAll方法:
notify方法通知调用了wait方法,但是尚未激活的一个线程进入线程调度队列(即进入锁竞争),注意不是立即执行。并且具体是哪一个线程不能保证。另外一点就是被唤醒的这个线程一定是在等待wait所释放的锁。
notifyAll方法则唤醒所有调用了wait方法,尚未激活的进程进入竞争队列。
3 synchronized关键字:
第一点:synchronized用来标识一个普通方法时,表示一个线程要执行该方法,必须取得该方法所在的对象的锁。
第二点:synchronized用来标识一个静态方法时,表示一个线程要执行该方法,必须获得该方法所在的类的类锁。
第三点:synchronized修饰一个代码块。类似这样:synchronized(obj) { //code.... }。表示一个线程要执行该代码块,必须获得obj的锁。这样做的目的是减小锁的粒度,保证当不同块所需的锁不冲突时不用对整个对象加锁。利用零长度的byte数组对象做obj非常经济。
4 atomic action(原子操作):
在JAVA中,以下两点操作是原子操作。但是c和c++中并不如此。
第一点:对引用变量和除了long和double之外的原始数据类型变量进行读写。
第二点:对所有声明为volatile的变量(包括long和double)的读写。
另外:在java.util.concurrent和java.util.concurrent.atomic包中提供了一些不依赖于同步机制的线程安全的类和方法。
5 一个例子,该例子模仿多人存取同一个账户:
Account类:
package com.synchronize;
import java.util.HashMap;
import java.util.Iterator;
public class Account {
private static HashMap<String, Integer> m = new HashMap<String, Integer>();
private static long times = 0;
static {
m.put("ren", 1000);
}
public synchronized void save(String name, int num) {
long tempTime = times++;
System.out.println("第 " + tempTime + " 次存储" + num + "之前" + name + "的余额为:" + m.get(name));
m.put(name, m.get(name) + num);
this.notify();
System.out.println("第 " + tempTime + " 次存储" + num + "之后" + name + "的余额为:" + m.get(name));
}
public static int get(String name) {
return m.get(name);
}
/**
* 注意wait的用法,必须在loop中,必须在拥有锁的代码块中。 前者是当被notify的时候要重新进行条件判断,后者是为了释放锁。
*
* @param name
* @param num
*/
public synchronized void load(String name, int num) {
long tempTime = times++;
System.out.println("第 " + tempTime + " 次提取" + num + "之前" + name + "的余额为:" + m.get(name));
try {
while (m.get(name) < num) {
System.out.println("第 " + tempTime + " 次提取" + "余额" + m.get(name) + "不足,开始等待wait。");
this.wait();
System.out.println("第 " + tempTime + " 次提取操作被唤醒");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
m.put(name, m.get(name) - num);
System.out.println("第 " + tempTime + " 次提取" + num + "之后" + name + "的余额为:" + m.get(name));
}
}
User类:
package com.synchronize;
/**
* 这里注意runnable接口的线程是怎么实例化的。new Thread(new User())
* 这里成功展示了多个用户存取同一个账户的多线程实例,通过多线程同步,保证了安全的执行。
* @author abc
*
*/
public class User implements Runnable {
private static Account account = new Account();
private final int id;
User(int i){
id=i;
}
public void run() {
int tempMoney = 100;
account.load("ren", tempMoney);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
account.save("ren", 100);
System.out.println("线程"+id+"完毕========================================================");
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(new User(i)).start();
}
}
}
6、下面是自己写的,一个经典的消费者和生产者的例子:
1、ObjLock.java
/**
* 生产者(producer)与消费者(consumer)问题
* 说明事物锁与多线程同步
* 生产者生产,消费者消费,规则:但当库存为0时,消费者要消费是不行的;
* 但当库存为上限(这里是10)时,生产者也不能生产
*/
public class ObjLock implements Runnable {
* 生产者(producer)与消费者(consumer)问题
* 说明事物锁与多线程同步
* 生产者生产,消费者消费,规则:但当库存为0时,消费者要消费是不行的;
* 但当库存为上限(这里是10)时,生产者也不能生产
*/
public class ObjLock implements Runnable {
private int count = 0; //产品数
private int locknum = 0; //上锁的线程数
public ObjLock(int n){
this.count = n;
}
//生产
public synchronized void produce(){
while(count == 10){
locknum ++;
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
count ++;
if(locknum > 0)
locknum --;
notify();
}
//消费
public synchronized void consume(){
while(count == 0){
locknum ++;
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
count --;
if(locknum > 0)
locknum --;
notify();
}
public void run() {
while(true){
if(Thread.currentThread().getName().substring(0, 8).equals("producer"))
produce();
else if(Thread.currentThread().getName().substring(0, 8).equals("consumer"))
consume();
System.out.println(Thread.currentThread().getName() + ": " + count + " ,locknum: " + locknum);
}
}
private int locknum = 0; //上锁的线程数
public ObjLock(int n){
this.count = n;
}
//生产
public synchronized void produce(){
while(count == 10){
locknum ++;
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
count ++;
if(locknum > 0)
locknum --;
notify();
}
//消费
public synchronized void consume(){
while(count == 0){
locknum ++;
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
count --;
if(locknum > 0)
locknum --;
notify();
}
public void run() {
while(true){
if(Thread.currentThread().getName().substring(0, 8).equals("producer"))
produce();
else if(Thread.currentThread().getName().substring(0, 8).equals("consumer"))
consume();
System.out.println(Thread.currentThread().getName() + ": " + count + " ,locknum: " + locknum);
}
}
}
2、TestObjLock测试类
public static void main(String[] args) {
ObjLock ol = new ObjLock(1);
Thread th1 = new Thread(ol,"producer");
Thread th2 = new Thread(ol,"consumer");
Thread th3 = new Thread(ol,"producer");
Thread th4 = new Thread(ol,"consumer");
Thread th5 = new Thread(ol,"producer");
Thread th6 = new Thread(ol,"consumer");
th1.start();
th2.start();
th3.start();
th4.start();
th5.start();
th6.start();
}
ObjLock ol = new ObjLock(1);
Thread th1 = new Thread(ol,"producer");
Thread th2 = new Thread(ol,"consumer");
Thread th3 = new Thread(ol,"producer");
Thread th4 = new Thread(ol,"consumer");
Thread th5 = new Thread(ol,"producer");
Thread th6 = new Thread(ol,"consumer");
th1.start();
th2.start();
th3.start();
th4.start();
th5.start();
th6.start();
}
注意:这里所以生产和消费都必须有notify(),避免死锁。不信的可以去掉其中一个,可以测试实现。
我记得大学学数据库的时候,也有说到这类问题。
评论
1 楼
lliiqiang
2012-09-06
我的个人理解:wait方法是在java虚拟机层面上在获取对象锁的时候暂时放弃持有锁,并且等待其他获取该锁的时候调用该锁对象的notify方法从而再次试图获取锁(此时仍然是用重新试图获得锁,即如果有线程获得该锁,仍然要等待该线程释放该锁之后,再获得该锁从而继续往下执行)
发表评论
-
google开放的maps api接口
2012-01-12 22:51 1168google开放的Maps api接口,包括很多版 ... -
iphone中请求对应的Mime type
2011-09-21 10:03 2245Extension MIME type Desc ... -
Sina微博开放平台获得App key和App secret
2011-08-20 18:01 2198最近由于需要调用微博开放接口,花点时间研究。刚上手,希望与 ... -
HttpURLConnection调用服务器,servlet中request.getInputStream为空
2011-08-18 14:01 2067HttpURLConnection调用服务器,servlet中 ... -
求质数的算法
2011-07-09 21:22 3430求i到j之间的所有质数最笨的一种方法是把i到j之间的每一个数n ... -
saveToken(request)
2011-07-09 21:21 1023Struts的Token(令牌)机制能够很好的解决表单重复提交 ... -
Method类invoke方法的使用
2011-07-09 21:20 2340java.lang.reflect.Methodpubli ... -
Hibernate的session.flush做了什么呢?
2011-07-09 21:20 939这是在一次事务提交 ... -
Hessian
2011-07-09 21:19 1135Hessian是一个轻量级的remoting onhttp ... -
HttpInvoker远程调用实例
2011-07-09 21:18 1138一、服务器端: 1、服务接口与实现类 ... -
几种通讯协议的比较
2011-07-09 21:18 905一、综述 本文比较了RM ... -
序列化
2011-07-09 21:17 1123无意当中想到这个问题,然后google 一下。找到一篇对 s ... -
对象的序列化和反序列化
2011-07-09 21:17 1007当两个进程在进行远 ... -
spring机制
2011-07-09 21:17 1129提到spring,第一印象就是DI与IOC,虽然有概念上的 ... -
如何让页面自动加载js文件
2011-07-09 21:16 2485打开页面时,对比缓存中js中是否有需要加载的js,如果有直 ... -
ajax的xmlhttp
2011-07-09 21:15 1004什么是xmlhttp一种浏览器不离开页面主动向服务器请求数据的 ... -
vo,bo,po,dto,dao,pojo
2011-07-09 21:15 1394vo,bo,po,dto,dao,pojo PO: ... -
Hql传中文参数出现乱码解决办法
2011-07-09 21:15 1126Hql传中文参数出现乱码(同sql传中文参数出现乱码一样): ... -
js四舍五入
2011-07-09 21:14 1268/* * 四舍五入的相关问题 */ / ... -
Session.Clear()、Session.Abandon()的区别
2011-07-09 21:13 1762Session.Clear()就是把Session对象中的 ...
相关推荐
java多线程下wait和notify的作用
5. Java多线程学习(四)等待/通知(wait/notify)机制 6. Java多线程学习(五)线程间通信知识点补充 7. Java多线程学习(六)Lock锁的使用 8. Java多线程学习(七)并发编程中一些问题 9. Java多线程学习(八...
单线程程序 多线程程序 Thread类的run方法和start方法 线程的启动 线程的启动(1)——利用Thread类的子类 线程的启动(2)——利用Runnable接口 线程的暂时停止 线程的共享互斥 synchronized方法 synchronized阻挡 ...
wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视。本文对这些关键字的使用进行了描述。 在 Java 中可以用 wait、notify 和 notifyAll 来实现...
本资源致力于向您介绍 Java 并发编程中的线程基础,涵盖了多线程编程的核心概念、线程的创建和管理,以及线程间通信的基本方法。通过深入学习,您将建立扎实的多线程编程基础,能够更好地理解和应用多线程编程。 多...
线程:Java多线程的实现方式,包括继承Thread类和实现Runnable接口。 锁:Java中的锁机制,包括synchronized关键字和ReentrantLock类。 线程池:Java中的线程池机制,包括线程池的创建、执行任务、关闭等操作。 并发...
Java自1995年面世以来得到了广泛得一个运用,但是对多...在Java 5.0之前Java里的多线程编程主要是通过Thread类,Runnable接口,Object对象中的wait()、 notify()、 notifyAll()等方法和synchronized关键词来实现的。
分享的多线程技术不是告诉你什么是线程,线程的状态,而是我们在开发中容易踩的坑,受过的伤害。我不会告诉你什么是爱情,但是我会告诉你爱过。 一 基础: 1,Thread.sleep(0)的作用 2,为什么线程会带来性能问题 3...
读者将通过使用java.lang.thread类、synchronized和volatile关键字,以及wait、notify和notifyall方法,学习如何初始化、控制和协调并发操作。此外,本书还提供了有关并发编程的全方位的详细内容,例如限制和同步、...
采用同步机制synchronized/wait(notify)或者lock(unlock)/condition variable实现两个producer和一个consumer之间协调运行。运行结果输出格式为:Put(or Get) number {[content] length start_index end_index} 包含...
一、重点知识 isDaemon 判断是否为守护线程。...如果没有线程处于wait状态,调用notify此时是一个空唤醒 stringBuffer中的同步方法,都是非静态的,因为共用一个this锁就可以了,线程进去调用他的一个方法
60、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不...同步的实现方面有两种,分别是synchronized,wait与notify 67、线程的基本概念、线程的基本状态以及状态之间的关系
JDK 5.0 是用 Java 语言创建高可伸缩的并发... <br>本教程将介绍 JDK 5.0 提供的用于并发的新实用程序类,并通过与现有并发原语(synchronized、wait() 和 notify())相比较,说明这些类如何提高了可伸缩性。
多线程实例 生产者、消费者有讲解 下面是其中一小部分代码 public synchronized void putShareChar(char c) { // 通知消费者已经生产,可以消费 if (isProduced) { // 如果产品还未消费,则生产者等待 try { ...
主要介绍了深入探究Java多线程并发编程的要点,包括关键字synchronized的使用和wait()与notify()获取对象锁的三种方式,需要的朋友可以参考下
了解多线程所带来的安全风险.mp4 从线程的优先级看饥饿问题.mp4 从Java字节码的角度看线程安全性问题.mp4 synchronized保证线程安全的原理(理论层面).mp4 synchronized保证线程安全的原理(jvm层面).mp4 单例问题...
文章目录1 wait、notify、notifyAll简单介绍1.1 使用方法 + 为什么不是Thread类的方法1.2 什么时候加锁、什么时候释放锁?1.3 notify、notifyAll的区别2 两个比较经典的使用案例2.1 案例1 — ABCABC。。。三个线程...
同步的实现方面有两种,分别是synchronized,wait与notify 4、String 和StringBuffer的区别 JAVA平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String类提供...
多线程锁 并发下的集合类 List Set Map Callable接口 线程创建的方式 callable / runnable FutureTask JUC常用辅助类 CountDownLatch (减少计数器) CyclicBarrier(加法计数器) Semaphore(信号量,流量控制) ...