andysern 2016-10-14 03:52 采纳率: 6.3%
浏览 1874

java的阻塞while如何避免并发量大时不掉数据呢

在做一个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做了另一个封装而已,那实现原理呢?

请大神指点一下。

  • 写回答

1条回答 默认 最新

  • wzgiceman 2016-10-17 03:16
    关注

    可以考虑使用心跳检测的方法来实现连接和传递数据,这样成本能小很多,而且不会有阻塞的问题!更加安全,可以直接使用第三方netty开源项目实现

    评论

报告相同问题?

悬赏问题

  • ¥15 高德地图点聚合中Marker的位置无法实时更新
  • ¥15 DIFY API Endpoint 问题。
  • ¥20 sub地址DHCP问题
  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题
  • ¥15 训练的多模态特征融合模型准确度很低怎么办