同步运行就是指需要传送数据的多个线程必须同步运行,步调一致,以保证传送的数据被及时和准确的收到,显然仅有关键字synchronized是不够的,虽然关键字synchronized阻止并发的更新一个对象,但是他们没有实现线程间传递数据。Thread类为此提供从object类继承过来的wait(),notify(),notifyAll()三个函数。
应用举例:一边向buffered中放数据一边取数据,假设缓冲区的大小为1
package Winter;
class Buffer2{
private int value;
private boolean isEmpty=true;//value是否为空的信号量
synchronized void put(int i)//放数据
{
while(!isEmpty)
{
try{
this.wait();
}catch(InterruptedException e)
{
System.out.println(e.getMessage());
}
}
value=i;
isEmpty=false;
notify();
}
synchronized int get(){//取数据
while(isEmpty){
try{
this.wait();
}catch(InterruptedException e){System.out.println(e.getMessage());}
}
isEmpty=true;
notify();
return value;
}
}
class Get2 extends Thread{//取数据线程
private Buffer2 bf;
public Get2(Buffer2 bf){this.bf=bf;}
public void run()
{
for(int i=1;i<6;++i)
System.out.println("\t\t Get2 get:" +bf.get());
}
}
public class Put2 extends Thread {//放数据线程
/**
* @param args
*/
private Buffer2 bf;
public Put2(Buffer2 bf){this.bf=bf;}
public void run()
{
for(int i=1;i<6;++i)
{
bf.put(i);
System.out.println("put2 put:"+i);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Buffer2 bf=new Buffer2();
(new Put2(bf)).start();
(new Get2(bf)).start();
}
}
wait()方法是当前线程变为阻塞状态,并主动释放互斥锁,这一点和sleep方法不同的地方,sleep方法不会释放互斥锁。
notify()唤醒等待队列的其他线程继续执行,是这些线程变成可运行状态。
notifyAll()唤醒等待队列中的全部线程继续执行。
生产者和消费者举例:
package Winter;
class Godown{
public static final int max_size=100;
public int curnum;
Godown(){}
Godown(int num){this.curnum=num;}
public synchronized void produce(int neednum)
{
while(this.curnum+neednum>Godown.max_size)
{
System.out.println("要生产的产品数量:"+neednum+"和剩余库存量:"+this.curnum+"之和超过了最大库存量,暂时不能执行生产任务!!");
try{
wait();
}catch(InterruptedException e)
{
System.out.println(e.getMessage());
}
}
this.curnum+=neednum;
System.out.println("已经生产"+neednum+"个产品,当前的库存量为:"+curnum);
notifyAll();
}
public synchronized void consume(int neednum)
{
while(neednum>this.curnum)
{
System.out.println("要消费"+neednum+"个产品,大于当前的库存量"+this.curnum+",暂时不能消费");
try{
wait();
}catch(InterruptedException e)
{
System.out.println(e.getMessage());
}
}
this.curnum-=neednum;
System.out.println("已经消费了"+neednum+"个产品,现在库存量为"+this.curnum+"个产品");
notifyAll();
}
}
class Produce extends Thread{//生产者线程
private int neednum;
private Godown godown;
Produce(Godown a1,int num)
{
this.godown=a1;
this.neednum=num;
}
public void run()
{
this.godown.produce(neednum);
}
}
class Consumer extends Thread{//消费者线程
private int neednum;
private Godown godown;
Consumer(){}
Consumer(int num,Godown a1)
{
this.neednum=num;
this.godown=a1;
}
public void run()
{
this.godown.consume(neednum);
}
}
public class Psc {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Godown godown=new Godown(10);
new Produce(godown,10).start();
new Consumer(20,godown).start();
}
}