java代码

1.根据session获取客户端的ip地址

        String clientIP = "";
        try {
            InetAddress  inetAddress  = ((NettyChannel) iSession.getCurChannel()).getRemoteAddress().getAddress();
            byte[] ipAddress = inetAddress.getAddress();
            for (int i = 0; i < ipAddress.length; i++) {
                if (i > 0) {
                    clientIP += ".";
                }
                clientIP += ipAddress[i] & 0xFF;
            }
        } catch (Exception e) {
            // e.printStackTrace();
        }

2.新增对外的curl接口

import com.google.gson.Gson;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ConfigurableApplicationContext;

import java.net.InetSocketAddress;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.io.BufferedReader;


public class RPCGmServerTask extends Thread{
    private static final Logger LOGGER = LoggerFactory.getLogger(RPCGmServerTask.class);

    public RPCGmServerTask(){
    }

    @Override
    public void run() {
        try {
            HttpServer server = HttpServer.create(new InetSocketAddress(2720), 0);
            server.createContext("/", new MyHandler());
            server.setExecutor(null); // creates a default executor
            server.start();
        } catch (Exception e) {
            LOGGER.error("run->{}", e);
        }
    }

    static class MyHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            InputStream is = exchange.getRequestBody();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String inputLine;
            while ((inputLine = br.readLine()) != null) {
                System.out.println(inputLine);
                try {
                    String cmd = inputLine.toString();
                    if (cmd.startsWith("//")) {
                        System.out.println("gmgmgm:" + cmd.substring(2));
                        String cmd2 = cmd.substring(2);
                        GmService.exeCmd(cmd2);
                    }
                } catch (Exception e) {
                    System.out.print("gmException" + e);
                }
            }
            exchange.sendResponseHeaders(200, 0);
            exchange.close();
        }
    }

}

3.jar包的各种启动方式超详细总结

jar包的各种启动方式超详细总结_java_脚本之家

1.java -jar

java -jar test.jar

弊端1:exit 退出终端会导致java进程中断。
弊端2:ctrl+c 退出启动展示页会导致java进程中断。
弊端3:直接关闭终端会导致java进程中断(启动时和启动完关闭都会导致java进程终端)。
弊端4:控制台日志不打印(这个可以不算弊端吧,其实很多场景不需要这个日志,这里姑且算是吧)

2.java -jar test.jar &

弊端1:直接关闭终端会导致java进程中断(启动时和启动完关闭都会导致java进程终端)。
弊端2:控制台日志不打印(这个可以不算弊端吧,其实很多场景不需要这个日志,这里姑且算是吧)

3.nohup java -jar test.jar

弊端1:exit 退出终端会导致java进程中断。
弊端2:ctrl+c 退出启动展示页会导致java进程中断。
弊端3:直接关闭终端会导致java进程中断(启动时和启动完关闭都会导致java进程终端)。

4.nohup java -jar test.jar &

弊端1:日志定向输出当前文件夹下的nohup.out(与下面几个命令相比,姑且算是弊端吧)

5.nohup java -jar test.jar > ./info.log &

该命令没有弊端,与上一个场景的区别是会将日志打印到指定的info.log下面。不过打印方式是覆盖。也就是说每次启动以后,都会将之前的日志覆盖

6.nohup java -jar test.jar >> ./info.log &

该命令没有弊端,与上一个场景的区别是会将日志打印到指定的info.log下面。不过打印方式是拼接。也就是说每次启动以后,都会将本次的日志拼接到原日志之后进行输出,这里日志因为是控制台日志,一般没必要拼接

7.nohup java -jar test.jar >> /dev/null &

这个命令是将日志输出到/dev/null,/dev/null是linux系统里的黑洞,其实可以理解为垃圾桶,相当于把日志扔了不要了,其他就没什么区别了。

4. CopyOnWriterArrayList 

CopyOnWriterArrayList 详解_copyonwritearraylist-CSDN博客

1. 简介

在 ArrayList 的类注释上,JDK 就提醒了我们,如果要把 ArrayList 作为共享变量的话,是线程不安全的,推荐我们自己加锁或者使用 Collections.synchronizedList 方法,其实 JDK 还提供了另外一种线程安全的 List,叫做 CopyOnWriteArrayList。

2. 原理

很多时候,我们的系统应对的都是读多写少的并发场景。CopyOnWriteArrayList容器允许并发读,读操作是无锁的,性能较高。至于写操作,比如向容器中添加一个元素,则首先将当前容器复制一份,然后在新副本上执行写操作,结束之后再将原容器的引用指向新容器。

线程安全的,多线程环境下可以直接使用,无需加锁;
通过锁 + 数组拷贝 + volatile 关键字保证了线程安全;
每次数组操作,都会把数组拷贝一份出来,在新数组上进行操作,操作成功之后再赋值回去。

从整体架构上来说,CopyOnWriteArrayList 数据结构和 ArrayList 是一致的,底层是个数组,只不过 CopyOnWriteArrayList 在对数组进行操作的时候,基本会分四步走:

加锁;
从原数组中拷贝出新数组;
在新数组上进行操作,并把新数组赋值给数组容器;
解锁。

除了加锁之外,CopyOnWriteArrayList 的底层数组还被 volatile 关键字修饰,意思是一旦数组被修改,其它线程立马能够感知到,代码如下:

private transient volatile Object[] array;
整体上来说,CopyOnWriteArrayList 就是利用锁 + 数组拷贝 + volatile 关键字保证了 List 的线程安全。

5.--spring.config.location命令学习

--spring.config.location命令主要是为了加载springBoot jar 外部的配置文档,比如我们可以将日志的级别控制放在jar外面的配置文档中,可以方便线上调试,不用改动jar中的配置文档,再打包这样比较麻烦的操作。

注意:当使用了这个命令后外面的配置文档级别要高于里面的文档,所以外面的属性会覆盖里面的,当然所有文档都是互补的,没有的话就相互补充。 

#!/bin/bash

package="gameSrv.jar"
cfg="./assets/config/gameSrv.properties"
log="./logs/gameSrv.log"
mypackage=$PWD/$package
nohup java -jar $package --spring.config.location=$cfg --mypackage=$mypackage >> $log 2>&1 &

sleep 5
PID=$(ps -ef | grep $mypackage | grep -v grep | awk '{ print $2 }')
if [ -z "${PID}" ]; then
    echo start ${mypackage} fail
else
    echo start ${mypackage} success ${PID}
fi

 6.Caused by: java.io.IOException: Connection reset by peer

这个错误的意思是:对方主机(peer)在建立连接时发送了一个重置连接的请求,导致连接中断。这可能是由于对方主机遇到了一些问题,或者是对方主机关闭了连接。

7.StringBuffer与StringBuider  

深度剖析Java中StringBuffer与StringBuider两个类的异同_stirngbuffer和-CSDN博客

StringBuffer

String 的值是不可变的,每次对String的操作都会生成新的String对象,不仅效率低,而且耗费大量内存空间。

StringBuffer类和String类一样,也用来表示字符串,但是StringBuffer的内部实现方式和String不同,在进行字符串处理时,不生成新的对象,在内存使用上要优于String。StringBuffer 默认分配16字节长度的缓冲区,当字符串超过该大小时,会自动增加缓冲区长度,而不是生成新的对象。
StringBuffer不像String,只能通过 new 来创建对象,不支持简写方式

StringBuffer str1 = new StringBuffer();  // 分配16个字节长度的缓冲区
StringBuffer str2 = =new StringBuffer(512);  // 分配512个字节长度的缓冲区
// 在缓冲区中存放了字符串,并在后面预留了16个字节长度的空缓冲区
StringBuffer str3 = new StringBuffer("青00 studyjava");

 主要方法

StringBuffer str = new StringBuffer(“biancheng100”);
str.append(true);
则对象str的值将变成”biancheng100true”。

StringBuffer str = new StringBuffer("abcdef");
str. deleteCharAt(3);
该代码将会删除索引值为3的字符,即”d“字符。

StringBuffer str = new StringBuffer("abcdef");
str.delete(1, 4);
该代码会删除索引值为1~4之间的字符,包括索引值1,但不包括4。


StringBuffer str = new StringBuffer("abcdef");
str.insert(3, "xyz");
最后str所指向的字符串为 abcdxyzef。

StringBuffer str = new StringBuffer("abcdef");
str.setCharAt(3, 'z');
该代码将把索引值为3的字符修改为 z,最后str所指向的字符串为 abczef。

StringBuilder

StringBuilder类和StringBuffer类功能基本相似,方法也差不多,主要区别在于StringBuffer类的方法是多线程安全的,而StringBuilder不是线程安全的,相比而言,StringBuilder类会略微快一点。

  • 操作少量的数据使用 String;
  • 单线程操作大量数据使用 StringBuilder;
  • 多线程操作大量数据使用 StringBuffer。

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值