java notifyall wait_Java同步方式(2)——wait和notify/notifyall

Java 中除了关键字

synchronized

能够实现线程同步外,还可以使用 wait 和 notify/notify 实现同步。

wait 方法是使拥有当前对象(object)的线程(thread)放弃锁(release lock),进入睡眠状态

notify 通知

该对象(object)

因上面

调用

wait而等待的某一进程重新唤醒启动

notifyAll 通知在对象(object)上因调用wait而等待的所有进程启动,这些进程根据优先级顺序执行

一个线程在其生命周期内总是处于某种状态:

创建: 当一个线程对象被声明并创建后,它处于“创建”状态;

就绪:线程对象调用 start() 方法后,将进入“就绪”状态,处于“就绪”状态的线程不是立即执行,而是进入就绪队列,等待CPU;

运行:当就绪队列中具有最高优先级的就绪线程被调度并获得CPU时,便进入“运行”状态,执行 run() 方法,run 方法中定义了线程的操作和功能;

非运行:处于“运行”状态的线程可能因为某些原因 (例如人为挂起)进入“非运行”状态,让出CPU并临时中止自己的执行;

停止:线程完成了它的全部工作或调用 stop() 方法强制中止线程,线程就进入“停止”状态。

1340634665_1699.png

wait 与 sleep 区别

wait

sleep

归属类

属于Object类(java.lang.

Object

)

属于Thread类(java.lang.

Thread

),静态方法

释放锁

释放了锁,其它线程同步块或方法

没有释放锁,不出让系统资源(如cpu)

中断唤醒

wait一般不会加时间限制,而是判断是否满足符合条件;

如果符合条件,则notify/notifyall唤醒

sleep(milliseconds)后自动唤醒,

如果时间不到可用interrupt()强制中断

适用范围

同步方法或同步块使用(synchronized)

任何地方都可使用(main、thread线程)

捕获异常

必须捕获异常(try/catch)

不需要捕获异常

wait - sleep 示例

(区别)

package com.homer.thread;

public class waitsleep {

public static void main(String[] args) {

ThreadDemo th = new ThreadDemo();

th.start();

System.out.println("thread is starting...");

synchronized (th) {

try {

System.out.println("Waiting for th to complete...");

//th.wait(1000);// 等待1秒后,立刻执行

th.wait();// 线程等待,notify唤醒后执行

} catch (Exception e) {

e.printStackTrace();

}

System.out.println("Total is : " + th.total);// 线程唤醒后,执行

}

}

}

class ThreadDemo extends Thread {

int total;

@Override

public void run(){

try {

Thread.sleep(2000);// 睡眠2秒

synchronized(this){

System.out.println("Thread is running...");

for(int i=0; i<10; i++) {

total += i;

System.out.println("i = " + i + "; total = " + total);

if(i==5) {

System.out.println("i = 5 sleep(3000)");

Thread.sleep(3000);// i = 5时,睡眠3秒

}

}

this.notify();

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

运行结果:

thread is starting...

Waiting for th to complete...

Thread is running...

i = 0; total = 0

i = 1; total = 1

i = 2; total = 3

i = 3; total = 6

i = 4; total = 10

i = 5; total = 15

i = 5 sleep(3000)

i = 6; total = 21

i = 7; total = 28

i = 8; total = 36

i = 9; total = 45

Total is : 45

================================

wait - notify 示例

(生产者 - 消费者)

package com.homer.thread;

public class waitnotify {

public static void main(String[] args) {

Q q = new Q();

new Producer(q);

new Consumer(q);

}

}

class Producer implements Runnable {

Q q = null;

public Producer(Q q) {

this.q = q;

(new Thread(this, "Producer")).start();

}

@Override

public void run() {

int i = 0;

while(i<5) {

q.put(i++);

}

}

}

class Consumer implements Runnable {

Q q = null;

public Consumer(Q q) {

this.q = q;

(new Thread(this, "Consumer")).start();

}

@Override

public void run() {

while(q.get()<5){

}

}

}

class Q {

int n;

boolean valueSet = false;

public synchronized int get() {

if(!valueSet) {// if valueSet == false,wait else try to got value

try {

wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.println("Get n : " + n);

valueSet = false;

notify();

return n;

}

public synchronized void put(int n) {

if(valueSet) {// if valueSet == true,already have value so wait fetch,else put

try {

wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

this.n = n;

System.out.println("Put n : " + n);

valueSet = true;

notify();

}

}

运行结果:

Put n : 0

Get n : 0

Put n : 1

Get n : 1

Put n : 2

Get n : 2

Put n : 3

Get n : 3

Put n : 4

Get n : 4

首先两个线程启动,他们的执行占用CPU多少随机,但是这里因为加了一个锁的Boolean型变量,而控制了put与set.

首先:创建了一个对象Q,创建了一个Producer,一个Consumer,这两个对象在构造方法中启动了线程.

第一步:

对于Producer来说,会首先去调用put方法,因为valueSet是默认值是false,所以在Q的put方法不执行wait 而是执行 this.n = n 赋值操作,执行完毕后设置为

valueSet =

true

对于Consumer来说,会首先去调用get方法,因为valueSet是默认值是false,所以该线程会执行wait(等待valueSet 赋值状态为true)

第二步

对于Producer来说,因为valueSet已经变成true,所以会wat.

对于Consumer来说,因为valueSet已经变成true,所以会执行下面的code(get value),然后设置valueSet为false.

第三步

Producer执行put方法,因为valueSet为false

Consumer等待(重复第一步)

依次类推,方法执行...

这里关键是加了一个共享的变量 valueSet 来判是该取值get,还是put值。当然有了wait跟notify才使它成为了可以实现的。

但是不管怎样,wait是使目前控制该对象(Q的对象q)的线程wait(等待),notify是使前面在该对象上面wait的方法继续执行.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值