netty构建socket问题记录和解决

1.递归问题

public class Test2 {

    public static void main(String args[]) {
       System.out.print(test(1));
    }
    private static ExecutorService exec = Executors.newFixedThreadPool(1);
    /**
     * 初步理解递归是因为方法返回阻塞,造成方法堆积,异步可用解决
     * EXEC 方式执行,虽然只有一个线程,但是这样做不耽误方法返回,测试不会造成OOM
     * @param i
     * @return
     */

    private static int test( int i){
        i++;
        if(i<100000){
//            new Thread(new Runnable() {
//                @Override
//                public void run() {
//                    test(2);
//                }
//            }).start();
            exec.execute(new Runnable() {
                @Override
                public void run() {
                    test(2);
                }
            });
        }
        return i;
    }
}
解读:正在情况下,递归多了会造成OOM,通过exec.execute执行不至于耽误上个方法返回,经过测试,可用有效避免OOM.

2.通道的频繁重连可能最终导致OOM
问题解读,通过分析 channel相关的 hashcode和 channeled等信息,确认重连之后,channel是一个全新的
channel对象,所以老的channel对象需要回收和关闭掉,否则会造成多channel链接现象(实验证明),经过测试,可用避免OOM问题

private void recycleChannel(){
    if(mChannel != null){
        Channel channel = mChannel;
        channel.deregister();
        channel.close();
        KidSocketLog.addTag("mChannel卸载流程执行");
    }
}
 
3.hot observale memory leak
this.kidObservable = Observable.fromEmitter(new Action1<Emitter<KidSocketData>>() {
    @Override
    public void call(final Emitter<KidSocketData> emitter) {
        final KidSocketCallBack kidSocketCallBack = new KidSocketCallBack() {
            @Override
            public void socketMessageArrived(SocketMessageBean messageBean) {
                KidSocketLog.addTag("socketMessageArrived:"+messageBean==null?"messageBean=null":messageBean.getDataMessage());
                emitter.onNext(messageBean);
            }
        };
        emitter.setCancellation(new Cancellable() {
            @Override
            public void cancel() throws Exception {
                KidSocketLog.addTag("kidSocketCallBackManager unregister kidSocketCallBack"+kidSocketCallBack.toString());
                kidSocketCallBackManager.unRegister(kidSocketCallBack);
            }
        });

        KidSocketLog.addTag("kidSocketCallBackManager register kidSocketCallBack"+kidSocketCallBack.toString());
        kidSocketCallBackManager.register(kidSocketCallBack);
    }
}, Emitter.BackpressureMode.BUFFER);
红色部分是后来加的,否则会造成callback在取消订阅后依然存在,取消订阅后,就算callback  执行,订阅者
也不会收到,但是calback还存在是没有意义的,造成内存泄漏 

4.多线程操作变量问题
public void receiveSocketMsg(SocketMessageBean socketMessageBean){
    try {
        KidSocketLog.addTag("receiveSocketMsg执行");
        if(kidSocketCallBackList != null){
            List<KidSocketCallBack> operationKidSocketCallBackList = new ArrayList<KidSocketCallBack>();
            operationKidSocketCallBackList.addAll(kidSocketCallBackList);
            KidSocketLog.addTag("operationKidSocketCallBackList size="+operationKidSocketCallBackList.size());
            for (KidSocketCallBack kidSocketCallBack:operationKidSocketCallBackList){
                kidSocketCallBack.socketMessageArrived(socketMessageBean);
            }
        }else {
            KidSocketLog.addTag("kidSocketCallBackList === null,不通过回调下发消息");
        }
    }catch (Throwable e){
        KidSocketLog.addTag("receiveSocketMsg 执行异常",e);
    }
}
为什么要把 callback新创建一个 List<KidSocketCallBack> operationKidSocketCallBackList呢,因为直接操作原始的list,原来的list可能东西被移除了,
我又在遍历,了能会导致线程并发问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值