首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

Java生产者消费者例证,大家看还有哪里可以改进? Java多线程 wait和notify运用 synchronized运用

2013-07-04 
Java生产者消费者例子,大家看还有哪里可以改进? Java多线程 wait和notify运用 synchronized运用Java生产者

Java生产者消费者例子,大家看还有哪里可以改进? Java多线程 wait和notify运用 synchronized运用


Java生产者消费者例子,大家看还有哪里可以改进? Java多线程 wait和notify运用 synchronized运用





1.模拟商店 (进货/销售)Shop.java



package com.cloud.factory;
import java.util.ArrayList;
import java.util.List;
import com.cloud.pojo.Product;
/**
 * 模拟商店 (进货/销售)
 */
public class Shop {
private static int i = 0;
// 产品的容器;达到容器暂停生产,消费到0等待生产
private static List<Product> list;
static {
list = new ArrayList<Product>();
}
/**
 * 生产产品
 */
public synchronized void produ() {
if (list.size() >= 5) {
try {
System.out.println(this.getClass()+"--------------生产商品" + i
+ "时,达到了总数暂停生产-------");
this.wait();// 使当前生产产品的线程 进入休眠
} catch (InterruptedException e) {
System.out.println(e.toString());
e = null;
}
} // 生产商品
Product product = new Product();
product.setName("商品" + i+1);
list.add(product);
System.out.println(this.getClass()+"生产了商品---->" + product.getName() + "商品总数" + i+1);
System.out.println(this.getClass()+"容器容量" + list.size());
i++;
super.notify();
}
/**
 * 消费产品
 * @return
 */
public synchronized void cousu() {
if (list.size() == 0) {// 消费完时,挂起
System.out.println(this.getClass()+"+++++++++++++++++++++++商品消费完了.等待+++++++++++++++=");
try {
this.wait();//使当前消费产品的线程 进入休眠
} catch (InterruptedException e) {
System.out.println(e.toString());
e = null;
}
}
Product product = list.get(0);
list.remove(0);
System.out.println(this.getClass()+"消费者获得了商品-->" + product.getName());
System.out.println(this.getClass()+"容器容量" + list.size());
super.notify();
}
}






2.实体类Product.java



package com.cloud.pojo;
/**
 * Product.java
 */
public class Product {
/**产品名称*/
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}





3.消费者Cousumer.java



package com.cloud.thread;
import java.util.Random;
import com.cloud.factory.Shop;
/**
 * 消费者
 */
public class Cousumer implements Runnable {
private Shop shop;// 要去消费的商店
public Cousumer(Shop shop) {
this.shop = shop;
}
public void run() {
while (true) {
try {
System.out.println(this.getClass()+" 开始消费...");
int couTime = new Random().nextInt(3000);//生成0-3000毫秒的随机数
Thread.sleep(couTime);
shop.cousu();
System.out.println(this.getClass()+" 消费了一件产品。耗时"+couTime+"毫秒。");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}





4.生产者Producer.java





package com.cloud.thread;
import java.util.Random;
import com.cloud.factory.Shop;
/**
 * 生产者   
 */
public class Producer implements Runnable {
private Shop shop;// 要去送货的商店
public Producer(Shop shop) {
this.shop = shop;
}
public void run() {
while (true) {
try {
System.out.println(this.getClass()+" 开始生产...");
int proTime = new Random().nextInt(3000);//生成0-3000毫秒的随机数
Thread.sleep(proTime);
shop.produ();
System.out.println(this.getClass()+" 生产了一件产品。耗时"+proTime+"毫秒。");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}





5.测试客户端Client.java



package com.cloud.test;
import com.cloud.factory.Shop;
import com.cloud.thread.Cousumer;
import com.cloud.thread.Producer;
/**
 * 测试客户端
 */
public class Client {
// 测试代码
public static void main(String[] args) {
Shop shop = new Shop();// 商店
Producer pro = new Producer(shop);
Cousumer cou = new Cousumer(shop);
new Thread(pro, "pro").start();
new Thread(cou, "cou").start();
}
}

Java多线程 wait和notify运用 synchronized运用 Java生产者消费者 Thread
[解决办法]
没细看代码,看到了一个使用不当的地方:
一定要在循环中调用wait()方法。

贴上JDK API中对wait方法的注意点:
在没有被通知、中断或超时的情况下,线程还可以唤醒一个所谓的虚假唤醒 (spurious wakeup)。虽然这种情况在实践中很少发生,但是应用程序必须通过以下方式防止其发生,即对应该导致该线程被提醒的条件进行测试,如果不满足该条件,则继续等待。换句话说,等待应总是发生在循环中,如下面的示例:

synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
     }


原因详见<深入java虚拟机>第二版一书的344页
[解决办法]
虽然楼主这里只有一个生产者,一个消费者,只要写代码仔细,不会出现虚拟唤醒,但还是注意点为好吧。。。



[解决办法]
欢迎技术牛人
[解决办法]
interface:

//实体接口
public interface IEntity {
public void on();
public void off();
}
//命令接口
public interface ICommand {
public void OnExecute();
public void OffExecute();
public void setIEntity(IEntity entity);
}
//容器接口
public interface IContainer {
public void pushCommand(ICommand command);
public ICommand popCommand();
}


具体实现:

public class EntityImpl implements IEntity{
//实体状态
private boolean flag = true;

@Override
public void on() {
this.flag = true;
System.out.println("实体状态:  " + this.flag);
}

@Override
public void off() {
this.flag = false;
System.err.println("实体状态: " + this.flag);
}
}

public class CommandImpl implements ICommand{

private IEntity entity = null;//实体

public CommandImpl(EntityImpl entity){
this.entity = entity;
}

@Override
public void OffExecute() {
entity.off();
}
@Override
public void OnExecute() {
entity.on();
}

@Override
public void setIEntity(IEntity entity) {
this.entity = entity;
}

}

public class ContainerImpl implements IContainer{
private static IContainer container = new ContainerImpl();

//模拟栈
private ICommand[] stack = null;
private int index = 0;

/**
 * 私有构造方法
 */
private ContainerImpl(){ 
this.stack = new ICommand[10];
}

/**
 * 获取容器
 * @return
 */
public static IContainer getContainerInstance(){
return container;
}


/**
 * push command
 */
@Override
public synchronized void pushCommand(ICommand command) {
while(index == this.stack.length){
try {
super.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

this.stack[index] = command;
++this.index;
System.out.print("+ [Thread:"+ Thread.currentThread().getName() + " 添加命令成功]");
command.OnExecute();
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.notifyAll();
}

/**
 * pop command
 */
@Override
public synchronized ICommand popCommand() {
while(index == 0){
try {
super.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

--this.index;
ICommand command = this.stack[index];

System.err.print("- [Thread:"+ Thread.currentThread().getName() + " 获取命令成功]");
command.OffExecute();

try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.notifyAll();
return command;
}
}

生产者:

public class Producers_Thread implements Runnable{
private IContainer container = null;


public Producers_Thread(IContainer container){
this.container = container;
}
@Override
public void run() {
while(true){
this.container.pushCommand(new CommandImpl(new EntityImpl()));


}
}
}


消费者:

public class Consumer_Thread implements Runnable{
private IContainer container = null;


public Consumer_Thread(IContainer container){
this.container = container;
}

@Override
public void run() {
while(true){
this.container.popCommand();
}
}

}

测试:

public class Main {
public static void main(String[] args){
IContainer container = ContainerImpl.getContainerInstance();

Thread pt_1 = new Thread(new Producers_Thread(container));
pt_1.setName("pt_1");
Thread pt_2 = new Thread(new Producers_Thread(container));
pt_2.setName("pt_2");

Thread ct_1 = new Thread(new Consumer_Thread(container));
ct_1.setName("ct_1");
Thread ct_2 = new Thread(new Consumer_Thread(container));
ct_2.setName("ct_2");
Thread ct_3 = new Thread(new Consumer_Thread(container));
ct_3.setName("ct_3");

pt_1.start();
pt_2.start();

ct_1.start();
ct_2.start();
ct_3.start();
}
}

热点排行