在做一个socket的小应用,在监听是否有数据输入时使用了while,其中有Thread.sleep(10),主要是为了防止cpu满负载。因为服务器是单CPU的,之前就出现了这个情况,如果直接while没有sleep的话,CPU很快就100%了。
如果我Socket socket = server.accept();包裹在一个while里,那是否在并发量多的时候,就一定会有一些连接丢失?
while(!stop){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
String con = null;
try {
con = is.readUTF();
} catch (IOException e1) {
e1.printStackTrace();
stop = true;
}
if(con!=null)putRevData(con);//putRevData是一个ArrayList,将收到的数据先存入队列里等待处理
}
这里的readUTF好像也是阻塞的,应该不会丢失。
但是如果是
while(true){
Thread.sleep(10);
socket = server.accept();
if(socket != null){
//做处理。这里将开启新的线程,并将其放入一个HashMap中,等待其他连接进入
}
}
如果是这样的话,那是否在并发多的时候,就会有sokcet接收不到了呢?
我自己做了一个测试,用for不断的输入数据,在阻塞接收中有很多数据就掉了。
如果放入数据的线程sleep大于接收数据的sleep,就能全接收到数据,但是一旦小于就会不通程度的丢失数据。
class TestSleep extends Thread{
private ArrayList a = new ArrayList();
String rev = null;
boolean stop,start = false;
public synchronized void push(){
this.a.add(rev);
rev = null;
}
public void shut(){
this.stop = true;
}
public synchronized void put(String a){
this.rev = a;
}
public synchronized void setRevNull(){
this.rev = null;
}
public void show(){
System.out.println(a);
}
public boolean isStart(){
return this.start;
}
public void run(){
while(!stop){
if(!this.start)
this.start = true;
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
if(rev!=null){
push();
}
}
show();
}
}
class putA extends Thread{
TestSleep ts = null;
String con = null;
putA(TestSleep a){
this.ts = a;
}
void setStr(String a){
con = a;
}
public void run(){
ts.put(con);
}
}
public class TempTest {
public static void main(String[] args) throws JSONException, IOException, InterruptedException {
TestSleep a = new TestSleep();
a.start();
Map<Integer,putA> map = new HashMap<Integer,putA>();
for(int i = 0;i<10;i++){
Thread.sleep(4);
putA b = new putA(a);
b.setStr("num"+i);
map.put(i, b);
b.start();
}
System.out.println(map.size());
Iterator<Map.Entry<Integer, putA>> entries = map.entrySet().iterator();
while(map.size()!=0){
while(entries.hasNext()){
Map.Entry<Integer, putA> entry = entries.next();
if(!entry.getValue().isAlive())entries.remove();
}
}
a.shut();
}
}
这是一个很矛盾的事情。因为while里必须得用一个sleep才能避免cpu负载的问题,但是如果一旦加了sleep,在并发量大的时候一定会有数据掉的。
想到了可以用java.nio的包来监听。但是好像Nio的包也只是对传统阻塞io做了另一个封装而已,那实现原理呢?
请大神指点一下。