[学习笔记]Java并发编程(详解wait(), notify(),sleep())

1.notify()
具体是怎么个意思呢?就是用来唤醒在此对象上等待的单个线程。说的有点太专业。打个比方,现在有十栋大房子,里面有很多被上了锁的房间,奇怪的是锁都是一样的,更不可思议的是,现在只有一把钥匙。而此时,张三用完钥匙后,就会发出归还钥匙的提醒,就相当于发出notify()通知,但是要注意的是,此时钥匙还在张三手中,只不过,当张三发出notify()通知后,JVM从那些整个沉睡的线程,唤醒一个。对应本例子,就是从其余的九栋大房子中唤醒一家,至于提醒谁来拿这把钥匙,就看JVM如何分配资源了。等到张三把钥匙归还后,那个被提醒的哪家,就可以使用该把钥匙来开房间门了。与此相对应的,还有一个notifyAll()方法。这是什么意思呢,还是本例,张三嗓门大,这时吼了一嗓子,即notifyAll(),所有沉睡的线程全都被吵醒了,当张三归还钥匙后,他们就可以竞争了,注意,刚才是JVM自动分配,而此时是线程之间竞争,比如优先级等等条件,是有区别的。

需要注意的是notify()方法执行后,并不是立即释放锁,而是等到加锁的代码块执行完后,才开始释放的,相当于本例中,张三只是发出了归还的通知,但是钥匙还没有归还,需要等到代码块,执行完后,才可以归还。

2.wait()
这个方法又是怎么个意思呢?当执行到这个方法时,就把钥匙归还,开始睡觉了。Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。

下面来看一个例子,加入我们要实现三个线程之间的同步操作,如何来实现呢?加入有三个线程分别用来输出A/B/C,如何能够三个线程之间顺序执行呢?这时候就需要采取线程之间同步的操作了,详见下面的代码。
[java] view plain copy print?
<span style="font-family:Comic Sans MS;font-size:18px;">package com.test; 


public class MyThreadPrinter2 implements Runnable { 

private String name; 
private Object prev; 
private Object self; 

private MyThreadPrinter2(String name, Object prev, Object self) { 
this.name = name; // A B C 
this.prev = prev; // c a b 
this.self = self; // a b c 


@Override 
public void run() { 
int count = 10; 
while (count > 0) { 
// 加锁,锁的钥匙是prev 
synchronized (prev) { 
// 一把锁,锁的钥匙是self变量 
synchronized (self) { 
System.out.print(name); 
count--; 
try { 
Thread.sleep(1); 
} catch (InterruptedException e) { 
e.printStackTrace(); 

// 唤醒另一个线程,但是也需要把本线程执行完后,才可以释放锁 
self.notify(); //a b c 


try { 
// 释放对象锁,本线程进入休眠状态,等待被唤醒 
prev.wait(); //睡觉觉了,等待被叫醒吧 // c a b 
} catch (InterruptedException e) { 
e.printStackTrace(); 






public static void main(String[] args) throws Exception { 
Object a = new Object(); 
Object b = new Object(); 
Object c = new Object(); 
MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a); 
MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b); 
MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c); 

new Thread(pa).start(); 
// 这样才可以保证按照顺序执行 
Thread.sleep(10); 
new Thread(pb).start(); 
Thread.sleep(10); 
new Thread(pc).start(); 
Thread.sleep(10); 

}</span> 

下面来分析一下,首先通过线程之间的同步操作,上面的例子就会按照线程的顺序来分别执行,最终输出的结果就是ABCABCABC..............。
在此还是打一个比方,程序刚开始的时候,创建了三个线程的对象,也就是代表有三座大房子,下面开始执行了,第一个大房子里面有一个叫做张三的人员,打开了一个房子的钥匙c,然后拿着钥匙a,又一次打开了这个房子里面的一个箱子,最后完成后,把箱子的钥匙a给归还了,执行完后,张三开始在这个c钥匙的房子里面漫长的沉睡,也就是prev.wati()方法;当第二个人李四来到房子后,同样执行一边操作,此时需要注意的是,李四扔出的是箱子钥匙b,并在a钥匙的房间随着了;好吧懒货,王五来到了第三个大房子,同样执行了一遍操作,注意的是,王五扔出的是箱子钥匙c,在钥匙b房子睡着了。

重点来了,王五扔出箱子钥匙c后,此时就把在房子钥匙c中的张三给唤醒了,等到王五把钥匙归还后,此时张三又开始周而复始的运作了;于是大家可以按照逻辑接着向下分析一下。

在整个例子中需要注意一下几点
1.为了保证几个线程先能够顺序执行,于是加入了Thread.sleep(10)
2.每个对象执行wait()或者notify()方法时,只能在同一把锁的房子里面,例如
synchronized (self) {
System.out.print(name);
count--;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 唤醒另一个线程,但是也需要把本线程执行完后,才可以释放锁
self.notify(); //a b c
}

房子的锁是self,所以执行self.notify()代表把我房子的钥匙给归还了。

有了上面的分析过程,下面我们出一道题,传统线程同步通信技术,子线程循环10次,接着主线程循环100次,又回到子线程循环10次,接着再回到主线程又循环100次,如此循环50次。这个例子又如何来实现呢?小编只在这里贴出源码,网上有很多解释的,可以按照小编的逻辑来分析一下。
[java] view plain copy print?
<span style="font-family:Comic Sans MS;font-size:18px;">package com.test; 


public class TraditionalThreadCommunication { 

/** 
* @param args 
*/ 
public static void main(String[] args) { 

final Business business = new Business(); 
new Thread( 
new Runnable() { 

@Override 
public void run() { 

for(int i=1;i<=50;i++){ 
business.sub(i); 




).start(); 

for(int i=1;i<=50;i++){ 
business.main(i); 





class Business { 
private boolean bShouldSub = true; 
public synchronized void sub(int i){ 
while(!bShouldSub){ 
try { 
this.wait(); 
} catch (InterruptedException e) { 
// TODO Auto-generated catch block 
e.printStackTrace(); 


for(int j=1;j<=10;j++){ 
System.out.println("sub thread sequence of " + j + ",loop of " + i); 

bShouldSub = false; 
this.notify(); 


public synchronized void main(int i){ 
while(bShouldSub){ 
try { 
this.wait(); 
} catch (InterruptedException e) { 
// TODO Auto-generated catch block 
e.printStackTrace(); 


for(int j=1;j<=100;j++){ 
System.out.println("main thread sequence of " + j + ",loop of " + i); 

bShouldSub = true; 
this.notify(); 


</span>
基于SSM框架的智能家政保洁预约系统,是一个旨在提高家政保洁服务预约效率和管理水平的平台。该系统通过集成现代信息技术,为家政公司、家政服务人员和消费者提供了一个便捷的在线预约和管理系统。 系统的主要功能包括: 1. **用户管理**:允许消费者注册、登录,并管理他们的个人资料和预约历史。 2. **家政人员管理**:家政服务人员可以注册并更新自己的个人信息、服务类别和服务时间。 3. **服务预约**:消费者可以浏览不同的家政服务选项,选择合适的服务人员,并在线预约服务。 4. **订单管理**:系统支持订单的创建、跟踪和管理,包括订单的确认、完成和评价。 5. **评价系统**:消费者可以在家政服务完成后对服务进行评价,帮助提高服务质量和透明度。 6. **后台管理**:管理员可以管理用户、家政人员信息、服务类别、预约订单以及处理用户反馈。 系统采用Java语言开发,使用MySQL数据库进行数据存储,通过B/S架构实现用户与服务的在线交互。系统设计考虑了不同用户角色的需求,包括管理员、家政服务人员和普通用户,每个角色都有相应的权限和功能。此外,系统还采用了软件组件化、精化体系结构、分离逻辑和数据等方法,以便于未来的系统升级和维护。 智能家政保洁预约系统通过提供一个集中的平台,不仅方便了消费者的预约和管理,也为家政服务人员提供了一个展示和推广自己服务的机会。同时,系统的后台管理功能为家政公司提供了强大的数据支持和决策辅助,有助于提高服务质量和管理效率。该系统的设计与实现,标志着家政保洁服务向现代化和网络化的转型,为管理决策和控制提供保障,是行业发展中的重要里程碑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值