多线程并发操作中,为了尽量减少同步锁的开销,一般都会尽可能减少同步操作。以下是一个多线程写入,写入操作需要同步,读取操作需要部分同步;读取操作的同步发生在缓冲区交换的时候。
以下是简单的java实现
package org.jf;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
/**
*
*
* 项目名称:Util
* 类名称:MyBuffer
* 类描述: 多线程写入 单线程读取
* 创建人:Administrator
* 创建时间:Mar 6, 2012 9:48:44 AM
* 修改人:Administrator
* 修改时间:Mar 6, 2012 9:48:44 AM
* 修改备注:
* @version
*
*/
public class Many2OneBuffer <T>{
private Object writeLock;
private int writeIndex=0;
private int readIndex=0;
private Object [] writeBuffer;
private Object [] readBuffer;
private int limit = -1;
private int readLimit = -1;
private int capacity ;
public Many2OneBuffer(int capacity)
{
this.capacity=capacity;
writeBuffer = new Object[capacity];
readBuffer = new Object[capacity];
writeLock = new Object();
}
public Many2OneBuffer()
{
this(500);
}
public boolean put(T obj)throws InterruptedException
{
synchronized(writeLock)
{
while(writeIndex == capacity)
{
writeLock.wait();
}
writeBuffer[writeIndex++] = obj;
limit++;
writeLock.notifyAll();
return true;
}
}
public boolean put(T obj,int timeout)throws InterruptedException
{
synchronized(writeLock)
{
if(writeIndex == capacity)
{
writeLock.wait(timeout*1000);
}
if(writeIndex == capacity)
{
return false;
}
writeBuffer[writeIndex++] = obj;
limit++;
writeLock.notify();
return true;
}
}
public T poll()throws InterruptedException
{
Object obj = null;
if(readLimit == -1)
{
if(limit == -1)
synchronized(writeLock)
{
while(limit == -1)
writeLock.wait();
}
// if(limit== -1)
// return null;
synchronized(writeLock)
{
//交换读写缓冲
Object [] tmp = null;
tmp = this.writeBuffer;
this.writeBuffer = this.readBuffer;
this.readBuffer = tmp;
readLimit = limit;
this.readIndex = 0;
this.writeIndex = 0;
this.limit = -1;
writeLock.notify();
}
}
//readLimit 必定大于0
if(readIndex == readLimit )
{
obj = readBuffer[readIndex++];
readLimit = -1;
}
else //if(readIndex<readLimit) readIndex 必定小于等于 readLimit
{
obj = readBuffer[readIndex++];
}
//
return (T)obj;
}
public boolean isFull()
{
return this.writeIndex == this.capacity;
}
public static void main(String args[]) throws InterruptedException
{
Many2OneBuffer buffer = new Many2OneBuffer(500);
WriteThread writeThread = new WriteThread(buffer);
writeThread.start();
PutThread putThread1 = new PutThread(buffer,"PutThread1");
PutThread putThread2 = new PutThread(buffer,"PutThread2");
PutThread putThread3 = new PutThread(buffer,"PutThread3");
PutThread putThread4 = new PutThread(buffer,"PutThread4");
putThread1.start();
putThread2.start();
putThread3.start();
putThread4.start();
Thread.sleep(6*10*1000);
putThread1.exit();
putThread2.exit();
putThread3.exit();
putThread4.exit();
writeThread.exit();
}
}
class PutThread extends Thread
{
Many2OneBuffer buffer ;
String rawStr;
boolean exit = false;
PutThread(Many2OneBuffer myBuffer,String rawStr)
{
buffer = myBuffer;
this.rawStr = rawStr;
}
public void run()
{
int i = 0;
while(!exit)
{
try {
boolean succ = buffer.put(rawStr+"_"+i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// if(!succ)
// System.out.println("put failed :"+rawStr+"_"+i);
i++;
}
// System.out.println("put thread exit_"+this.rawStr);
}
public void exit()
{
exit = true;
this.interrupt();
}
}
class WriteThread extends Thread
{
Many2OneBuffer buffer ;
boolean exit = false;
WriteThread(Many2OneBuffer myBuffer)
{
buffer = myBuffer;
}
public void exit()
{
exit = true;
}
public void run()
{
try {
BufferedWriter bw = new BufferedWriter(new FileWriter("e:/write.txt",false));
int count = 0;
while(!exit)
{
Object obj = buffer.poll();
if(obj!=null)
{
bw.write(obj.toString()+"\n");
count++;
bw.flush();
if(count==100)
{
this.sleep(100);
count = 0;
}
}
}
System.out.println("write thread exit");
bw.flush();
bw.close();
} catch (IOException e)
{
e.printStackTrace();
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
分享到:
相关推荐
缓冲区溢出则可能导致程序崩溃,或者更严重的是,攻击者可以利用它来执行任意代码,获得系统控制权。 在实际应用中,攻击者可能会利用这种漏洞进行数据盗窃、系统瘫痪甚至横向渗透。例如,如果一个移动应用使用易受...
而CVE-2017-10989则涉及到对RTree blob处理不当,导致缓冲区越界读取。 【SQL语句触发的内存破坏】 SQLite解释器允许更灵活的方式来触发SQL语句中的bug。如CVE-2015-3414和CVE-2015-3415所示,不正确的collation...
2. 一对多关系(One-to-Many): - 一个实体对象可以对应多个其他实体对象的实例,通常在多方的一端使用`List`或`Set`来存储关联对象。映射文件中使用`set`或`list`元素表示这种关系。 3. 多对多关系(Many-to-...
操作系统是计算机系统的核心组成部分,它管理着系统的硬件资源和软件资源...许多对一模型(Many-to-one)是指多个用户线程映射到一个内核线程,多对多模型(Many-to-many)则是用户线程与内核线程之间存在多对多关系。
- **关联映射的本质**:通过`<many-to-one>`标签将实体类与数据库表字段关联起来。 - **User实体类**:表示用户信息。 - **Group实体类**:表示用户所属的组信息。 - **Group实体类的映射文件**:定义了Group与User...
{7.10}缓冲字符输入输出流}{113}{section.7.10} {7.11}文件常用操作}{114}{section.7.11} {7.12}对象序列化}{117}{section.7.12} {8}多线程}{121}{chapter.8} {8.1}线程的常用属性与方法}{121}{section.8.1} {...
例如,`Department`的映射可能包含`<list>`元素表示`employees`,`Employee`的映射可能包含`<many-to-one>`表示`department`,`<set>`表示`roles`。 8. **基础编程题**: - 将`count`转换为`double`:`Double....
一对多关联(One-To-Many Associations) 6.5. 延迟初始化(延迟加载)(Lazy Initialization) 6.6. 集合排序(Sorted Collections) 6.7. 使用<idbag><br>6.8. 双向关联(Bidirectional Associations)...
一对多关联(One-To-Many Associations) 6.5. 延迟初始化(延迟加载)(Lazy Initialization) 6.6. 集合排序(Sorted Collections) 6.7. 使用<idbag><br>6.8. 双向关联(Bidirectional Associations)...
- `hasOne()`:表示一对多的关联关系。在一对多关系中,一个表(例如客户表)会有一个或多个相关联的记录在另一个表(例如订单表)中。例如,`$customer->orders` 会返回该客户下的所有订单数组。 - `hasMany()`:...
2. **as many as** - 多达:用来表示数量,强调达到或接近某个数量。 3. **get into trouble** - 陷入麻烦:指遇到问题或困难,可能需要解决或摆脱。 4. **make it to** - 到达:成功抵达某个地方或完成某件事。 ...