我正在写一个Nio的程序,要求是一个进行为主进程,通过Chanell以及Selecotr进行循环,并从Socket取得数据后
做为生产者送入Pipe,另个一个ThreadPool进行做为消费者从Pipe中取数据,但是发现了一个问题,有时候生产者
生产数据过快时,可能部分数据会丢失。那么Pipe到底是一个什么样的通道呢,它是的缓冲区有多大呢?
我写了一个程序进行测试
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Pipe;
public class B
{
public static int num = 5000;
static Pipe pipe;
static boolean flag = false;
static
{
try
{
pipe = Pipe.open();
pipe.sink().configureBlocking(true);
pipe.source().configureBlocking(true);
} catch (IOException e)
{
e.printStackTrace();
}
}
public static class B1 implements Runnable
{
ByteBuffer buf;
@Override
public void run()
{
System.out.println("Start create.");
for (int i = 0; i < num; i++)
{
String s = String.format("%08d", i);
buf = ByteBuffer.wrap(s.getBytes());
if (checkOut(i))
System.out.println(String.format("Create %d", i));
try
{
pipe.sink().write(buf);
} catch (IOException e)
{
e.printStackTrace();
}
}
System.out.println("Create end.");
flag = true;
}
}
public static boolean checkOut(int i)
{
boolean outflag = false;
if (i <= 3000)
{
if ((i % 500) == 0) outflag = true;
} else if (i < 4000)
{
if ((i % 100) == 0) outflag = true;
} else if (i < 4100)
{
if ((i % 10) == 0) outflag = true;
} else
{
outflag = true;
}
return outflag;
}
public static class B2 implements Runnable
{
@Override
public void run()
{
while (!flag)
{
Thread.yield();
}
/*
try
{
Thread.sleep(100);
} catch (InterruptedException e1)
{
e1.printStackTrace();
}*/
System.out.println("Start receive.");
ByteBuffer bb = ByteBuffer.allocateDirect(8);
byte[] bytebuf = new byte[8];
for (int i = 0; i < num; i++)
{
if (checkOut(i))
System.out.println(String.format("Receive %d", i));
try
{
bb.clear();
pipe.source().read(bb);
} catch (IOException e)
{
e.printStackTrace();
}
bb.flip();
bb.get(bytebuf, 0, 8);
String s = new String(bytebuf);
if (null == s)
System.out.println(String.format("ERR:%d", i));
else
{
String s1 = String.format("%08d", i);
if (s1.compareTo(s) != 0)
System.out
.println(String.format("ERR:%d /"%s/"", i, s));
}
}
System.out.println("receive end.");
}
}
public static void main(String[] argv)
{
new Thread(new B1()).start();
new Thread(new B2()).start();
}
}
运行结果:
Start create.
Create 0
Create 500
...
Create 4125
Create 4126
Create 4127
Create 4128
Create 4129
根据结果,可以判定,在阻塞模式下,Pipe的写入端当Pipe的缓冲区满的时候,后出现阻塞。
写入输出缓会在第4129处停下来,因此,Pipe的缓冲区有33024个字节,相当于32K+256个字节。
考虑到这样的结果,我在主线程中在Socket写入Pipe时,采用了非阻塞模式,并加入了相关是否
正确写入的判断,系统就运行正常了。
做为生产者送入Pipe,另个一个ThreadPool进行做为消费者从Pipe中取数据,但是发现了一个问题,有时候生产者
生产数据过快时,可能部分数据会丢失。那么Pipe到底是一个什么样的通道呢,它是的缓冲区有多大呢?
我写了一个程序进行测试
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Pipe;
public class B
{
public static int num = 5000;
static Pipe pipe;
static boolean flag = false;
static
{
try
{
pipe = Pipe.open();
pipe.sink().configureBlocking(true);
pipe.source().configureBlocking(true);
} catch (IOException e)
{
e.printStackTrace();
}
}
public static class B1 implements Runnable
{
ByteBuffer buf;
@Override
public void run()
{
System.out.println("Start create.");
for (int i = 0; i < num; i++)
{
String s = String.format("%08d", i);
buf = ByteBuffer.wrap(s.getBytes());
if (checkOut(i))
System.out.println(String.format("Create %d", i));
try
{
pipe.sink().write(buf);
} catch (IOException e)
{
e.printStackTrace();
}
}
System.out.println("Create end.");
flag = true;
}
}
public static boolean checkOut(int i)
{
boolean outflag = false;
if (i <= 3000)
{
if ((i % 500) == 0) outflag = true;
} else if (i < 4000)
{
if ((i % 100) == 0) outflag = true;
} else if (i < 4100)
{
if ((i % 10) == 0) outflag = true;
} else
{
outflag = true;
}
return outflag;
}
public static class B2 implements Runnable
{
@Override
public void run()
{
while (!flag)
{
Thread.yield();
}
/*
try
{
Thread.sleep(100);
} catch (InterruptedException e1)
{
e1.printStackTrace();
}*/
System.out.println("Start receive.");
ByteBuffer bb = ByteBuffer.allocateDirect(8);
byte[] bytebuf = new byte[8];
for (int i = 0; i < num; i++)
{
if (checkOut(i))
System.out.println(String.format("Receive %d", i));
try
{
bb.clear();
pipe.source().read(bb);
} catch (IOException e)
{
e.printStackTrace();
}
bb.flip();
bb.get(bytebuf, 0, 8);
String s = new String(bytebuf);
if (null == s)
System.out.println(String.format("ERR:%d", i));
else
{
String s1 = String.format("%08d", i);
if (s1.compareTo(s) != 0)
System.out
.println(String.format("ERR:%d /"%s/"", i, s));
}
}
System.out.println("receive end.");
}
}
public static void main(String[] argv)
{
new Thread(new B1()).start();
new Thread(new B2()).start();
}
}
运行结果:
Start create.
Create 0
Create 500
...
Create 4125
Create 4126
Create 4127
Create 4128
Create 4129
根据结果,可以判定,在阻塞模式下,Pipe的写入端当Pipe的缓冲区满的时候,后出现阻塞。
写入输出缓会在第4129处停下来,因此,Pipe的缓冲区有33024个字节,相当于32K+256个字节。
考虑到这样的结果,我在主线程中在Socket写入Pipe时,采用了非阻塞模式,并加入了相关是否
正确写入的判断,系统就运行正常了。