简单实现生产者、消费者模型
来源:互联网 发布:最好的期货软件 知乎 编辑:程序博客网 时间:2024/05/01 12:41
闲来无事,写了段生产者/消费者的代码。写的过程中遇到了一些问题,有些地方着实费了一番周折,特写此文以备后忘。
1.代码层次
实现中定义了四个类分别是comm、ReadPort、WritePort、SerialBuffer。
class comm:<main-class >
public class Comm ...{
public static void main(String[] args) ...{
SerialBuffer sb=new SerialBuffer();
ReadPort rp0=new ReadPort(sb);
ReadPort rp=new ReadPort(sb);
WritePort wp=new WritePort(sb);
WritePort wp1=new WritePort(sb);
rp0.start();
wp.start();
wp1.start();
rp.start( );
}
}class ReadPort:
function: 向临界区加入数据
class ReadPort extends Thread...{
private SerialBuffer serialBuffer;
private boolean isStop=false;
private byte[] b=new byte[]...{0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x20,0x21,0x22};
public ReadPort(SerialBuffer sb)...{
serialBuffer=sb;
}
public void run()...{
while(!isStop)...{
try...{
sleep(2000);
}catch(InterruptedException e)...{}
for(int i=1;i<50;i++)...{
serialBuffer.addInBuffer(b);
}
isStop=true;
}
}
}
class WritePort:
function:从临界区取出数据
class WritePort extends Thread...{
SerialPort serialPort;
OutputStream os;
private boolean isStop=false;
private SerialBuffer serialBuffer;
public WritePort(SerialBuffer sb)...{
serialBuffer=sb;
}
public void run()...{
while(!isStop)...{
try...{
sleep(2000);
}catch(InterruptedException e)...{}
serialBuffer.delFromBuffer();
}
}
}
class SerialBuffer:
function:临界区存储数据
class SerialBuffer...{
//默认size 和递增size
public static int SERIALBUFFER_SIZE=24;
public static int SERIALBUFFER_INCREMENT=512;
private ByteBuffer b;
private boolean debug=true;
public SerialBuffer()...{
b=ByteBuffer.allocateDirect(SERIALBUFFER_SIZE);
}
public synchronized void addInBuffer(byte[] _in)...{
System.out.println(" ====== "+Thread.currentThread().getName()+" 第"+(curNum++)+"次写入 ======");
while(b.position()==b.capacity()||(b.position()+_in.length>b.capacity()))...{
try...{
System.out.println("当前缓存区已满,不能再加入数据,暂时休眠.");
this.wait();
}catch(InterruptedException e)...{
System.out.println("异常:当前缓存区已满,暂时休眠.");
}
}
System.out.println("加入"+_in.length+"个字节");
b.put(_in);
notify();
}
public synchronized byte[] delFromBuffer()...{
System.out.print(" "+Thread.currentThread().getName()+" 开始取数据");
//flip();
//while(b.limit()==0){
for(b.flip();b.limit()==0;b.flip())...{//这里 返回到下文
try...{
System.out.println("当前无数据可取,暂时休眠.");
b.clear();
this.wait();
}catch(InterruptedException e)...{
System.out.println("异常:当前无数据可取,暂时休眠.");
}
}
System.out.println(Thread.currentThread().getName()+" 可以取数据。。。");
byte[] rebyte=new byte[b.limit()];
System.out.println("取出"+rebyte.length+"个字节");
b.get(rebyte);
b.clear();
notify();
return rebyte;
}
}
2.临界区处理
临界区使用了java nio中的byteBuffer作为数据缓存,第一次使用byteBuffer遇到了些小问题,在这里原本用flip();+while(conditions)
在一个生产者、一个消费者时没有问题,但是调整到多个生产者和多个消费者时,会抛出BufferUnderflowException异常
3.运行结果
设置1个生产者/2个消费者时的运行结果:
Thread-1 开始取数据当前无数据可取,暂时休眠.
Thread-2 开始取数据当前无数据可取,暂时休眠.
====== Thread-0 第1次写入 ======
加入12个字节
Thread-1 可以取数据。。。
取出12个字节
当前无数据可取,暂时休眠.
====== Thread-0 第2次写入 ======
加入12个字节
====== Thread-0 第3次写入 ======
加入12个字节
====== Thread-0 第4次写入 ======
当前缓存区已满,不能再加入数据,暂时休眠.
Thread-2 可以取数据。。。
取出24个字节
加入12个字节
====== Thread-0 第5次写入 ======
加入12个字节
====== Thread-0 第6次写入 ======
当前缓存区已满,不能再加入数据,暂时休眠.
Thread-1 开始取数据Thread-1 可以取数据。。。
取出24个字节
加入12个字节
====== Thread-0 第7次写入 ======
加入12个字节
====== Thread-0 第8次写入 ======
当前缓存区已满,不能再加入数据,暂时休眠.
Thread-2 开始取数据Thread-2 可以取数据。。。
取出24个字节
加入12个字节
====== Thread-0 第9次写入 ======
加入12个字节
====== Thread-0 第10次写入 ======
当前缓存区已满,不能再加入数据,暂时休眠.
Thread-1 开始取数据Thread-1 可以取数据。。。
取出24个字节
加入12个字节
====== Thread-0 第11次写入 ======
加入12个字节
====== Thread-0 第12次写入 ======
当前缓存区已满,不能再加入数据,暂时休眠.
Thread-2 开始取数据Thread-2 可以取数据。。。
取出24个字节
加入12个字节
====== Thread-0 第13次写入 ======
加入12个字节
====== Thread-0 第14次写入 ======
当前缓存区已满,不能再加入数据,暂时休眠.
Thread-1 开始取数据Thread-1 可以取数据。。。
取出24个字节
Thread-2 开始取数据当前无数据可取,暂时休眠.
加入12个字节
====== Thread-0 第15次写入 ======
加入12个字节
====== Thread-0 第16次写入 ======
当前缓存区已满,不能再加入数据,暂时休眠.
Thread-2 可以取数据。。。
取出24个字节
加入12个字节
====== Thread-0 第17次写入 ======
加入12个字节
====== Thread-0 第18次写入 ======
当前缓存区已满,不能再加入数据,暂时休眠.
Thread-1 开始取数据Thread-1 可以取数据。。。
取出24个字节
加入12个字节
====== Thread-0 第19次写入 ======
加入12个字节
Thread-2 开始取数据Thread-2 可以取数据。。。
取出24个字节
Thread-1 开始取数据当前无数据可取,暂时休眠.
Thread-2 开始取数据当前无数据可取,暂时休眠.
小结
对于多个生产者和多个消费者访问临界区时产生异常的问题,我分析产生的原因如下:1.首先要明确byteBuffer在读数据前需要调flip()方法,从而对position和limit以及remaining等值进行设置。2.是当取数据线程经过一次wait,再次由runnable转换为run状态时,由于当前运行环境可能已经发生了变化(即不同于此线程发生wait时的环境),所以需要重新flip()。但是flip()方法此时却访问不到,(在while(conditions)之外!)所以没有经过flip()直接get()就可能会抛出异常。
- 简单实现生产者、消费者模型
- 使用semaphore实现生产者-消费者简单模型
- 使用semaphore实现生产者-消费者简单模型
- 生产者-消费者模型实现
- 生产者、消费者简单实现
- 生产者消费者简单实现
- 简单的生产者消费者模型
- 超简单生产者消费者模型
- python生产者消费者简单模型
- 用BlockingQueue实现一个简单的生产者-消费者模型
- 简单实现带有数据缓冲池的生产者消费者模型
- 用BlockingQueue实现简单的生产者-消费者模型
- 用BlockingQueue实现一个简单的生产者-消费者模型
- socket 简单实现jms(消费者生产者模型)
- java实现生产者消费者模型
- 生产者消费者模型的实现
- LinkedBlockingQueue 实现生产者消费者模型
- OpenMP实现生产者消费者模型
- 怎么只显示一篇文章?有没有人来解决这个问题?
- DataGrid应用
- 树和自联表(四)
- 关于正版软件的使用
- Openlaszlo配合struts开发RIA常见的几个问题整理
- 简单实现生产者、消费者模型
- [ARX]如何得到当前CAD打印设备列表及其他打印设置内容
- 测试以下我的搏客
- 实用的生活小秘方.
- 删除数据库中对应的图片!
- 11月7#8#
- setmessage()&postmessage()
- nutch0.7.2+ictclas 成功移植到linux下。
- 计算某天是星期几【C代码】