当遇到一个线程要产生数据而另一个线程要处理数据时,这就是生产者消费者的关系。生产者在生产数据以后可以直接调用消费者处理数据,也可以将生产出来的数据,放到缓冲区中,等待消费者在缓冲区中取出数据然后再处理。第一种算是同步执行的,生产者将数据产生之后等待消费者将数据处理然后进行下一个数据的生产,当消费者处理数据的时间很长,那么会直接影响到生产者的效率。第二种方法算是异步的,当生产者将数据产生以后,将数据存储到一个缓冲区中,然后当消费者要处理数据时,会直接到缓冲区中去数据。当缓冲区中没有数据时,那么消费者就要等待生产者生产数据,当缓冲区中的数据存满时,那么生产者就要先等待消费者先处理一部分数据。
针对上面的描述的异步通信的场景创建两个类:Producer(生产者)和Consumer(消费者),其中生产者负责产生数据,且仅在缓冲区未满是产生数据;消费者负责处理数据,且仅在缓冲区不空是产生数据。
/** * 生产者 */ public class Producer implements Runnable{ ThreadInter ti = null; public Producer(ThreadInter ti){ this.ti = ti; } public void run(){ for(int i=0;i<10;i++){ Cola cola = new Cola(i); ti.push(cola); System.out.println("生产了:"+cola); try{ Thread.sleep(300); }catch(Exception e){ e.printStackTrace(); } } } } /**
* 消费者 */ public class Consumer implements Runnable{ ThreadInter ti = null; public Consumer(ThreadInter ti){ this.ti = ti; } public void run(){ for(int i=0;i<10;i++){ Cola cola = ti.pop(); System.out.println("消费了:"+cola); try{ Thread.sleep(600); }catch(Exception e){ e.printStackTrace(); } } } }
还有一个Cola角色类,代表生产的商品
public class Cola{ private int id; public Cola(int id){ this.id = id; } public String toString(){ return "Cola:"+id; } }
还需要创建一个处理缓冲区的类,同时处理线程是否生产和消费,线程之间的通信
public class ThreadInter{ private int index = 0; Cola[] colas = new Cola[6]; //将cola加入缓存数组中 public synchronized void push(Cola cola){ System.out.println("生产index:"+index); while(index == colas.length){ try{ this.wait(); }catch(Exception e){ e.printStackTrace(); } } this.notify(); colas[index] = cola; index++; } //将cola取出 public synchronized Cola pop(){ System.out.println("消费index:"+index); while(index==0){ try{ this.wait(); }catch(Exception e){ e.printStackTrace(); } } this.notify(); index--; return colas[index]; } }
最后测试主类
public class Main{ public static void main(String []args) { ThreadInter ti=new ThreadInter(); Producer p=new Producer(ti); Consumer c=new Consumer(ti); new Thread(p).start(); new Thread(c).start(); } }