啦啦啦!我又来了!我是超carry的MF!
线程间通信
生产者和消费者问题
假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走消费。
如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待,直到仓库中的产品被消费者取走为止。
如果仓库中放有产品,则消费者可以将产品取走消费,否则停止消费并等待,直到仓库中再次放入产品为止。
Java提供了3个方法解决线程之间的通信问题
方法名 | 作用 |
---|---|
final void wait() | 表示线程一直在等待,直到其他线程通知 |
void wait(long timeout) | 线程等待指定毫秒参数的时间 |
fiial void wait (long timeout ,int nanos) | 线程等待指定毫秒,微妙的时间 |
final void notify() | 唤醒一个处于等待状态的线程 |
final void notifyAll() | 唤醒同一个对象上所有调用wait()方法的线程,优先级别高的线程优先运行 |
均是java.lang.Object类的方法都只能在同步方法或者同步代码块中使用,否则会抛出异常
package 消费者和生产者;
/*
*厂库
*/
public class ShareData {
private char c;
private boolean isHaveShoping=false;//false代没有商品,true有商品了
/**
* 存放商品
*/
public synchronized void save( char c ){
if(isHaveShoping){
try {
wait();//等待商品被取走,阻塞着
} catch (InterruptedException e) {
e.printStackTrace();}}
System.out.println("进行存放商品");
System.out.println("存放进来了"+c);
this.c=c;
System.out.println("存放结束");
isHaveShoping=true;
notify();//唤醒消费者
}
/**
* 取商品的
* @return
*/
public synchronized char get(){
if(!isHaveShoping){
try {
wait();//等待被唤醒,生产者,有商品
} catch (InterruptedException e) {e.printStackTrace();}}
System.out.println("进行取商品");
System.out.println("取走"+c);
isHaveShoping=false;
//唤醒生产,你继续生产
notify();
return c;
}
}
定义生产者线程类和消费者线程类
package 消费者和生产者;
/**
* 生产者
*
* @author Administrator
*
*/
public class Producer extends Thread{
ShareData sd;
public Producer(ShareData sd) {
this.sd=sd;
}
@Override
public void run() {
for(char c='a'; c<='f' ; c++){//生产
try {
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
sd.save(c);//将商品存放在厂库中
}
}
}
package 消费者和生产者;
/**
* 消费者
*
* @author Administrator
*
*/
public class Consumer extends Thread{
private ShareData sd;
public Consumer(ShareData sd) {
this.sd=sd;
}
@Override
public void run() {
for(int i=0;i<6;i++){
try {
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("获取到了"+sd.get());
}
}
}
定义一个测试
package 消费者和生产者;
public class Test02 {
public static void main(String[] args) {
ShareData sd=new ShareData();
new Producer(sd).start();
new Consumer(sd).start();
}
}
运行结果
Sleep和wait的区别
这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类。
最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法.
使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用.
今天到此结束,下周见了!老铁们!(看到朋友圈里的各位大佬深感自己是个小菜,希望自己能够和大佬们一样进入心仪的公司)!!!!!
我认为比较好的一片文章,解释多线程下-生产者和消费者之间的关系,有图比较容易理解,可以去看看。