您的位置:首页 > 编程语言 > Java开发

Java模拟生产者消费者问题

2015-01-29 21:11 267 查看
Java模拟生产者消费者问题
一、Syncronized方法详解

解决生产者消费这问题前,先来了解一下Java中的syncronized关键字。

synchronized关键字用于保护共享数据。请大家注意"共享数据",你一定要分清哪些数据是共享数据,如下面程序中synchronized关键字保护的不是共享数据(其实在这个程序中synchronized关键字没有起到任何作用,此程序的运行结果是不可预先确定的)。这个程序中的t1,t2是 两个对象(pp1,pp2)的线程。JAVA是面向对象的程序设计语言,不同的对象的数据是不同的,pp1,pp2有各自的run()方法,而
synchronized使同一个对象的多个线程,在某个时刻只有其中的一个线程可以访问这个对象的synchronized数据。每个对象都有一个"锁标志",当这个对象的一个线程访问这个对象的某个synchronized数据时,这个对象的所有被synchronized修饰的数据将被上锁(因为" 锁标志"被当前线程拿走了),只有当前线程访问完它要访问的synchronized数据时,当前线程才会释放"锁标志",这样同一个对象的其它线程才有机会访问synchronized数据。

package SyncronizedMenthodTest;
 
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
 
public
class
PrintProgram implements Runnable {
 
    public
synchronized void
show() {
        PrintStreamps =
null
;
        try {
            ps = new PrintStream(new File("Test.txt"));
            for (int
i = 0; i < 100;
i++) {
                ps.append("这是" + Thread.currentThread().getName() +
"输出的" +
i + "\n");
            }
 
        }catch(IOException
e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            ps.close();
        }
    }
 
    @Override
    public
void
run() {
        show();
    }
 
    public
static void
main(String[]
args) {
        PrintProgrampp1=
new
PrintProgram();
        PrintProgrampp2=
new
PrintProgram();
        Threadt1 = new Thread(pp1);
        t1.setName("线程1");
        Threadt2 = new Thread(pp2);
        t2.setName("线程2");
        t1.start();
        t2.start();
    }
 
}
 

得到Test.txt中内容为:

但如果改为如下代码,则结果将不同:

package SyncronizedMenthodTest;
 
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
 
public
class
PrintProgram implements Runnable {
 
    public
synchronized void
show() {
        PrintStreamps =
null
;
        try {
            ps = new PrintStream(new File("Test.txt"));
            for (int
i = 0; i < 100;
i++) {
                ps.append("这是" + Thread.currentThread().getName() +
"输出的" +
i
                        +"\n");
            }
 
        }catch(IOException
e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            ps.close();
        }
    }
 
    @Override
    public
void
run() {
        show();
    }
 
    public
static void
main(String[]
args) {
        PrintProgrampp1 =
newPrintProgram();
        Threadt1 = new Thread(pp1);
        t1.setName("线程1");
        t1.start();
        Threadt2 = new Thread(pp1);
        t2.setName("线程2");
        t2.start();
    }
 
}
结果如下:

因为这里的synchronized保护的是共享数据。t1,t2是同一个对象(pp1)的两个线程,当其中的一个线程(例如:t2)开始执行run()方法时,由于run()受synchronized保护,所以同一个对象的其他线程(t1)无法访问synchronized方法(run方法)。只有当 t2执行完后t1才有机会执行。

二、 Java模拟生产者消费者问题
         了解了Java的syncronized关键字,那么生产者消费者问题也迎刃而解了。例如题目如下:

解决方案:

---------------

产品

---------------

package ProducerAndConsumerProblem;
 
public
class
Produce {
 
    /*
     * 生产者生产的产品
     */
    private String
name;
    private
double
price;
 
    @Override
    public String toString() {
        return
"Produce [name="+
name+ ", price=" +
price+ "]";
    }
 
    public Produce(String
name, double
price) {
        super();
        this.name =
name;
        this.price =
price;
    }
 
    public Produce() {
        super();
    }
 
    public String getName() {
        return
name;
    }
 
    public
void
setName(String name) {
        this.name =
name;
    }
 
    public
double
getPrice() {
        return
price;
    }
 
    public
void
setPrice(double
price) {
        this.price =
price;
    }
 
}
 

---------------

店员

---------------

package ProducerAndConsumerProblem;
 
public
class
Clerk {
    // 店员用于存放生产者生产的产品,最多放20个
    // 相当于一个缓冲区
    static
final int n
= 20;
    private
static
Produce[] produce =
new Produce[n];
 
    private
static int
produceNumber= 0;
    static
int
inIndex = 0;
    static
int
outIndex = 0;
 
    private
static
Object obj =
new
Object();
 
    public
static
Produce getProduce(int
index) {
        return
produce[index];
    }
 
    public
static void
setProduce(Produce
produce, int
index) {
        Clerk.produce[index] =
produce;
    }
 
    public
static
Object getObj() {
        return
obj;
    }
 
    public
static void
setObj(Object
obj) {
        Clerk.obj =
obj;
    }
 
    public
synchronized void
addProduce() {
 
        if (produceNumber>= 20) {
            try {
                wait();
            }catch(InterruptedException
e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }else{
            System.out.println(Thread.currentThread().getName()
                    +"生产了一个产品,放在店员" +
inIndex+
"那儿");
            Produceproduce=
new
Produce();
            Clerk.setProduce(produce,
inIndex);
            inIndex = (inIndex + 1) %
n;
            produceNumber++;
            notifyAll();
        }
    }
 
    public
synchronized void
getProduce() {
        if (produceNumber<= 0) {
            try {
                wait();
            }catch(InterruptedException
e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }else{
            System.out.println(Thread.currentThread().getName()+
"从"
                    +outIndex+
"号店员那儿取走一件商品");
            Clerk.setProduce(null,
outIndex);
            outIndex = (outIndex + 1) %
n;
            produceNumber--;
            notifyAll();
        }
    }
 
}
---------------

生产者

---------------

package ProducerAndConsumerProblem;
 
public
class
Producer implementsRunnable {
 
    Clerkclerk=null;
 
    public Producer(Clerk
clerk) {
        this.clerk =
clerk;
    }
 
    @Override
    public
void
run() {
        while (true) {
            try {
                Thread.sleep(1000);
            }catch(InterruptedException
e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            clerk.addProduce();
           
        }
    }
}
---------------

消费者

---------------

package ProducerAndConsumerProblem;
 
public
class
Consumer implementsRunnable {
 
    Clerkclerk= null;
 
    public Consumer(Clerk
clerk) {
        this.clerk =
clerk;
    }
 
    @Override
    public
void
run() {
        while (true) {
            try {
                Thread.sleep(1000);
            }catch(InterruptedException
e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            clerk.getProduce();
        }
    }
 
}
---------------

主函数

---------------

package ProducerAndConsumerProblem;
 
public
class
Test {
    public
static void
main(String[]
args) {
        Clerkclerk=new Clerk();
        Consumerconsumer=
new
Consumer(clerk);
        Threadt1 = new Thread(consumer);
        t1.setName("消费者");
        Producerproducer=
new
Producer(clerk);
        Threadt2 =new Thread(producer);
        t2.setName("生产者");
        t1.start();
        t2.start();
    }
}
---------------

显示结果

---------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: