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
classPrintProgram 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();
PrintProgrampp2=
newPrintProgram();
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
classPrintProgram 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
classProduce {
/*
* 生产者生产的产品
*/
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
classClerk {
// 店员用于存放生产者生产的产品,最多放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=
newProduce();
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
classProducer 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
classConsumer 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
classTest {
public
static void main(String[]
args) {
Clerkclerk=new Clerk();
Consumerconsumer=
newConsumer(clerk);
Threadt1 = new Thread(consumer);
t1.setName("消费者");
Producerproducer=
newProducer(clerk);
Threadt2 =new Thread(producer);
t2.setName("生产者");
t1.start();
t2.start();
}
}
---------------
显示结果
---------------
一、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
classPrintProgram 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();
PrintProgrampp2=
newPrintProgram();
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
classPrintProgram 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
classProduce {
/*
* 生产者生产的产品
*/
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
classClerk {
// 店员用于存放生产者生产的产品,最多放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=
newProduce();
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
classProducer 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
classConsumer 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
classTest {
public
static void main(String[]
args) {
Clerkclerk=new Clerk();
Consumerconsumer=
newConsumer(clerk);
Threadt1 = new Thread(consumer);
t1.setName("消费者");
Producerproducer=
newProducer(clerk);
Threadt2 =new Thread(producer);
t2.setName("生产者");
t1.start();
t2.start();
}
}
---------------
显示结果
---------------
相关文章推荐
- java模拟实现生产者---消费者问题
- 生产者消费者问题--JAVA模拟
- java多线程之生产者与消费者问题的简单模拟
- java简单模拟生产者消费者问题
- java 模拟实现消费者和生产者问题
- java模拟实现生产者---消费者问题
- java多线程模拟生产者消费者问题,公司面试常常问的题。。。
- java线程模拟生产者消费者问题
- java模拟实现生产者---消费者问题
- JAVA学习笔记(1)_____模拟线程通信之生产者消费者问题
- java多线程模拟生产者消费者问题
- 生产者消费者问题(java模拟)
- java模拟生产者消费者问题
- java模拟生产者与消费者问题(线程同步)
- 生产者消费者问题的Java实现
- java 线程模拟生产者和消费者
- java生产者与消费者问题
- JAVA多线程模拟生产者与消费者_实例
- 生产者与消费者问题(java多线程实现)
- java实现 生产者和消费者问题 多线程同步示例