读书人

经验4-线程同步通讯-生产者与销售者

发布时间: 2012-09-16 17:33:17 作者: rapoo

心得4--线程同步通讯-生产者与销售者

1. 分析:(生产者-消费者问题是多线程同步处理的典型问题)

有一块生产者和消费者共享的有界缓冲区,生产者往缓冲区放入产品,消费者从缓冲区取走产品,这个过程可以无休止的执行,不能因缓冲区满生产者放不进产品而终止,也不能因缓冲区空消费者无产品可取而终止。

2. 解决生产者消费者问题的方法

一种是采用某种机制保持生产者和消费者之间的同步

一种是在生产者和消费者之间建立一个管道

线程的同步解决生产者-消费者问题

限制公共缓冲区不能被两个线程同时访问,需要使用互斥锁,即用synchronized来标识同步资源。但加了互斥锁以后有可能会造出死锁。这时需要wait()方法和notify()方法--当前线程被阻塞并释放该对象的互斥锁

3. 通过上面的分析,大致了解了一下思路,下面用代码案例解说一下:

packagecom.javaEE.code.put;

//资源类

class Res{

String name;

String sex;

boolean b; //设置一个旗帜,用来判断运用wait()方法时是否释放资源,在这里声明的boolean型java系统默认为false。

}

//模拟生产者,生成产品

class Inputimplements Runnable{

private Res r;

public Input(Res r) {

this.r = r;

}

public void run() {

int x = 0;

while(true){

//运用线程同步来避免生成者还没生产消费者就来输出、生产者生产好多了消费者才来、输出产品混乱(比如此例中的姓名张三性别gril的劣质产品问题)问题隐患

synchronized(r){

if(r.b){ //这里为假暂不执行

try {

r.wait();

} catch(InterruptedException e) {

// TODOAuto-generated catch block

e.printStackTrace();

}

}

if(x==0){

r.name = "张三";

r.sex = "男";

}else{

r.name ="jane";

r.sex = "girl";

}

r.b = true; //将旗帜设置为假

r.notify(); //发出通讯,通知消费者

}

x = (x+1)%2;

}

}

}

//模拟消费者,输出产品

class Outputimplements Runnable{

private Res r;

public Output(Res r) {

this.r = r;

}

public void run() {

while(true){

synchronized(r){

if(!r.b){

try {

r.wait();

} catch(InterruptedException e) {

// TODOAuto-generated catch block

e.printStackTrace();

}

}

System.out.println("生产产品名称:"+r.name+"......"+"生成产品类别:"+r.sex);

r.b = false;

r.notify();

}

}

}

}

public classThreadPut {

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();

}

}

4.以上代码还可以优化,优化后的代码为:

这里用的是同步线程的synchronized函数,而上面例子中用的是代码块。这里把同步线程的代码都放到了资源类中。

packagecom.javaEE.code.put;

class Res1{

String name;

String sex;

boolean flag;

public synchronized void set(Stringname,String sex){

if(flag)

try {

wait();

} catch (InterruptedExceptione) {

// TODO Auto-generatedcatch block

e.printStackTrace();

this.name = name;

this.sex = sex;

flag = true;

notify();

}

}

public synchronized void out(){

if(!flag)

try {

wait();

} catch (InterruptedExceptione) {

// TODO Auto-generatedcatch block

e.printStackTrace();

}

System.out.println("生产产品名称:"+name+"......"+"生成产品类别:"+sex);

flag = false;

notify();

}

}

class Input1implements Runnable{

private Res1 r;

public Input1(Res1 r) {

this.r = r;

}

public void run() {

int x = 0;

while(true){

/*这里不像前面的例子,用个限制次数的for循环来终止循环,这里如果用for循环迭代语句i++并没有执行

就进入synchronized代码库中了,然后生产然后通知输出,通知完之后再次生产回到这里又重新开新了!*/

if(x==0){

r.set("张三", "男");

}else{

r.set("jane","girl");

}

x = (x+1)%2;

}

}

}

class Output1implements Runnable{

private Res1 r;

public Output1(Res1 r) {

this.r = r;

}

public void run() {

while(true){

r.out();

}

}

}

public classOptimizeThreadPut {

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();

}

}

读书人网 >编程

热点推荐