怎么办,好几天没写博客了,心里感觉不踏实。水一篇吧,水水更健康。在看Java线程这本书的电子版,看到第四章notify、wait、notifyAll这几个方法,前面的notify和wait还好,比较简单,就是需要注意的是notify和wait方法必须放在同步代码中。可是为什么要这样呢?原因是如果不将notify和wait放到同步代码中的话,他们之间可能会产生竞态条件。现设有两个线程,如果不将notify和wait放在同步代码中可能发生如下情况:
一、第一个线程检查条件,确定需要等待。
二、第二个线程设定条件。
三、第二个线程调用notify()方法,本次调用因为没有其他的等待线程而直接返回。
四、第一个线程调用wait()。
附上一段关于notify和wait的Android代码:
package com.wly.testwait_notify;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
int count = 0;
Button b;
CountThread countThread;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
b.setText(msg.arg1 + "");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
b = new Button(this);
b.setText("0");
this.setContentView(b);
countThread = new CountThread();
countThread.start();
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(countThread.isAlive()) {
countThread.wakeup();
}
}
});
}
class CountThread extends Thread {
@Override
public void run() {
super.run();
while(count < 20) {
sendMsg();
try {
sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//发送通知,并进入等待状态,注意wait()只能位于synchronized代码块中
public synchronized void sendMsg() {
Message msg = new Message();
msg.arg1 = count ++;
handler.sendMessage(msg);
if(count % 5 == 0) {
try {
System.out.println("--等待10秒--");
wait(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 唤醒线程,注意notify()只能位于synchronized代码块中
*/
public synchronized void wakeup() {
notify();
}
}
}
说出来有点好笑的是,笔者以前想在Android中用wait()结果因为没有放到同步代码块中,导致一运行就报错,还以为Android中不能用wait呢!咳咳,,不要笑啦,进入今天正题NotifyAll。可能是最近办公室比较吵得原因吧(抢票的抢票,聊天的聊天),使得笔者静不下心来,于是一个notifyAll盯着看了好久才看懂。
还是一样分析,为什么要有notifyAll,他和notify有什么区别吗?notifyAll用来唤醒一个对象上的多个等待线程。就是说首先这个对象有多个线程等待着使用该对象,其次就是要唤醒所有的线程,让他们去竞争对象上的锁。这里需要注意一下的是:虽然所有该对象上的等待线程都被唤醒了,但他们还需要获得对象上的锁才能向下运行。于是当调用notifyAll后还是只有那个获取到了锁的线程才能继续往下运行。好了,一段notifyAll的测试代码:
package com.wly.javathread.chap4;
/**
* 测试notifyAll方法
*
* @author wly
*
*/
public class TestNotifyAll implements Runnable {
static ResourcePool mPool;
public static void main(String[] args) {
ResourcePool pool = new ResourcePool();
System.out.println("总资源数:" + pool.resource_max);
TestNotifyAll tn_1 = new TestNotifyAll(pool);
TestNotifyAll tn_2 = new TestNotifyAll(pool);
TestNotifyAll tn_3 = new TestNotifyAll(pool);
TestNotifyAll tn_4 = new TestNotifyAll(pool);
new Thread(tn_1).start();
new Thread(tn_2).start();
new Thread(tn_3).start();
new Thread(tn_4).start();
}
@Override
public void run() {
while(true) {
mPool.getResource(2);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mPool.freeResource(1);
}
}
public TestNotifyAll(ResourcePool pool) {
this.mPool = pool;
}
static class ResourcePool {
int resource_max = 10; //资源最大数量
int resource_count = 0; //当前占用资源数量
/**
* 获取资源
* @param num
*/
public synchronized void getResource(int num) {
if((resource_count + num) <= resource_max) { //有可用资源,领取使用
resource_count += num;
System.out.println("线程" + Thread.currentThread().getId() + "拿到2个资源");
System.out.println("剩余资源数:" + (resource_max -resource_count));
} else { //无可用资源,等
try {
System.out.println("资源数量不够,线程" + Thread.currentThread().getId() + ":进入等待状态");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 释放资源
* @param num
*/
public synchronized void freeResource(int num) {
if(num <= (resource_count)) {
resource_count -= num;
System.out.println("释放" + num + "个资源,当前剩余资源" + (resource_max-resource_count));
notifyAll();
}
}
}
}
运行结果如下:
总资源数:10
线程9拿到2个资源
剩余资源数:8
线程11拿到2个资源
剩余资源数:6
线程8拿到2个资源
剩余资源数:4
线程10拿到2个资源
剩余资源数:2
释放1个资源,当前剩余资源3
线程9拿到2个资源
剩余资源数:1
释放1个资源,当前剩余资源2
线程11拿到2个资源
剩余资源数:0
释放1个资源,当前剩余资源1
资源数量不够,线程8:进入等待状态
释放1个资源,当前剩余资源2
线程10拿到2个资源
剩余资源数:0
释放1个资源,当前剩余资源1
资源数量不够,线程9:进入等待状态
释放1个资源,当前剩余资源2
线程11拿到2个资源
剩余资源数:0
释放1个资源,当前剩余资源1
资源数量不够,线程8:进入等待状态
释放1个资源,当前剩余资源2
线程10拿到2个资源
剩余资源数:0
释放1个资源,当前剩余资源1
资源数量不够,线程11:进入等待状态
释放1个资源,当前剩余资源2
线程9拿到2个资源
剩余资源数:0
释放1个资源,当前剩余资源1
资源数量不够,线程8:进入等待状态
释放1个资源,当前剩余资源2
线程10拿到2个资源
剩余资源数:0
可能运行结果需要仔细看才能看出流程,主要就是释放资源时通知所有等待线程,若此时某个等待线程抢到了锁会进行资源请求,或者进入等待状态(资源不够时)。
O啦~~~
转载请保留出处:http://blog.csdn.net/u011638883/article/details/18322537
谢谢!!