您的位置:首页 > 其它

多线程初探(八)

2016-01-19 17:08 176 查看
package com.liujunhua.ith02;
/**
* 线程的等待唤醒机制
* 两个线程对同一资源进行操作,为保证两者操作资源的独立性,出现了等待唤醒机制。
* 1.Input线程负责对变量赋值,为了避免在Input在具有CPU执行权时,进行重复的变量赋值动作,
*   当首次赋值后进行标记,当线程再次赋值的时候,先对标记进行判断,若已经赋值并且该数值还没有
*   被Output输出,Input线程就等待。即放弃执行权。
* 2.当Input等待的时候Output就会获得CPU执行权,就会执行相应的输出操作。当完成输出操作后,它将标记为已经操作状态。
*   当下次执行的时候,如果发现标记已经输出,并且Input没有进行新的赋值,那么就会进入等待状态。
*
* 从而实现了等待唤醒机制。
*
* wait();
* notify();
* notifyAll();
*
* 这些方法都使用在同步中,因为要对持有监视器(锁)的线程进行操作。
* 所以要使用在同步中,因为只有同步才具有锁。
*
* 但是为什么这些操作线程的方法要定义在Object类中呢?
*
* 那是因为这些方法在操作同步中的线程是,都必须要标识他们所操作线程的锁,
* 只有同一个锁上的被等待的线程,可以被同一个锁上的notify唤醒。
*
* 也就是说,等待和唤醒必须是同一个锁。
*
* 而锁可以是任意对象,所以可以被任意对象调用的方法定义在object类中。
*/
public class Demo01 {

public static void main(String[] args){

Res r = new Res();

Input in = new Input(r);
Output out = new Output(r);

Thread t1 = new Thread(in);
Thread t2 = new Thread(out);

t1.start();
t2.start();
}
}

class Res {

private String name;
private String sex;
private boolean flag = false;

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}

public void print(){
System.out.println(this.name+"........"+this.sex);
}
}

/**
* 这里线程锁的创建很有技巧性,如果仅仅是简单的obj对象,肯定是不行的,因为一个obj不可能在两个类里面都可以用。
* 但此时又需要两个同步代码块用同一个线程锁,这里便采用了两个线程共同操作的Res对象作为线程锁,很好的解决了线程的安全问题。
*/
class Input implements Runnable {

private Res r;

Input(Res r) {
this.r = r;
}

@Override
public void run() {
// TODO Auto-generated method stub
int mark = 0;

while (true) {

synchronized (r) {

if(r.isFlag())
try {
r.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (mark == 0) {
r.setName("mike");
r.setSex("man");
} else {
r.setName("丽丽");
r.setSex("女女");
}
mark = (mark + 1) % 2;

r.setFlag(true);
r.notify();
}

}
}

}

class Output implements Runnable {

private Res r;

Output(Res r) {
this.r = r;
}

@Override
public void run() {
// TODO Auto-generated method stub
while (true) {

synchronized (r) {

if(!r.isFlag()){
try {
r.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
r.print();
r.setFlag(false);
r.notify();
}

}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: