今天学习了等待唤醒机制,通过一个例子做个小小的总结。
需求是对某个数据进行修改和输出操作,要求两个操作同时进行,且先修改后输出。
设计思路:1,需要一个公共数据类。两个线程,一个Input、一个Output。
2,Input和Output应该是两个线程,这样才能同时进行。
3,Input和Output的对数据进行修改的方法应该实现同步,以解决线程安全问题。
4,需要有等待唤醒机制,这样才能实现先修改后输出。
实现代码:
//共享资源类,name和sex是被修改的数据,flag作为数据被修改之后的标识。
class Res{
String name;
String sex;
boolean flag=false;
}
class Input implements Runnable{
private Res r;
Input(Res r){
this.r=r;
}
public void run(){
int x=0;
while(true){
synchronized(r){
if(r.flag){//如果数据被修改过,那么写线程wait(),等待读线程完成后唤醒。
try {
r.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(x==0){
r.name="Mike";
r.sex="Man";
}else{
r.name="丽丽";
r.sex="女";
}
r.flag=true;//完成写操作后,将标志位改为true,表示写线程完成,唤醒其他线程。
r.notify();
}
x=(x+1)%2;
}
}
}
class Output implements Runnable{
private Res r;
Output(Res r){
this.r=r;
}
public void run(){
while(true){
synchronized(r){
if(!r.flag){//如果标志位为false,说明读线程完成,必须等待写线程操作。
try{
r.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println(r.name+"::"+r.sex);
r.flag=false;//读完之后将标志位改为false,表示读完,并唤醒写线程。
r.notify();
}
}
}
}
public class ThreadComm {
public static void main(String[] args) {
// TODO Auto-generated method stub
Res r=new Res();
Input in=new Input(r);
Output ou=new Output(r);
Thread t1=new Thread(in);
Thread t2=new Thread(ou);
t1.start();
t2.start();
}
}
class Res2{
private String name;
private String sex;
boolean flag=false;
public synchronized void set(String name,String sex){
if(flag){
try{
this.wait();
}catch(Exception e){
e.printStackTrace();
}
}
this.name=name;
this.sex=sex;
flag=true;
this.notify();
}
public synchronized void get(){
if(!flag){
try{
this.wait();
}catch(Exception e){
e.printStackTrace();
}
}
System.out.println(name+"::"+sex);
flag=false;
this.notify();
}
}
class Input2 implements Runnable{
private Res2 r;
Input2(Res2 r){
this.r=r;
}
public void run(){
int x=0;
while(true){
if(x==0){
r.set("Mick", "Man");
}else{
r.set("丽丽", "女女女女");
}
x=(x+1)%2;
}
}
}
class Output2 implements Runnable{
private Res2 r;
Output2(Res2 r){
this.r=r;
}
public void run(){
while(true){
r.get();
}
}
}
public class WaNoYouDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Res2 r=new Res2();
new Thread(new Input2(r)).start();
new Thread(new Output2(r)).start();
}
}