1. 案例说明,以下代码会立即执行结束即jvm退出
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.SelfSignedCertificate;
public class EchoExitServer1 {
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new LoggingHandler(LogLevel.INFO));
}
});
b.bind(18080).sync();//用同步方式绑定服务端监听端口,只有绑定不成功时阻塞
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
2. 此代码优化一点点
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.util.logging.Logger;
public class EchoExitServer2 {
static Logger logger = Logger.getLogger(EchoExitServer2.class.getName());
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new LoggingHandler(LogLevel.INFO));
}
});
ChannelFuture f = b.bind(18080).sync();
f.channel().closeFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
//业务逻辑处理代码,此处省略...
logger.info(future.channel().toString() + " 链路关闭");
}
});
} finally {
// bossGroup.shutdownGracefully();
// workerGroup.shutdownGracefully();
}
}
}
3. 使用 f.channel().closeFuture().sync(); //此处会阻塞main线程继续执行
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.util.logging.Logger;
public class EchoExitServer3 {
static Logger logger = Logger.getLogger(EchoExitServer3.class.getName());
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new LoggingHandler(LogLevel.INFO));
}
});
ChannelFuture f = b.bind(18080).sync();
f.channel().closeFuture().sync(); //此处会阻塞main线程继续执行
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
4. 再优化一点点
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.util.logging.Logger;
public class EchoExitServer4 {
static Logger logger = Logger.getLogger(EchoExitServer4.class.getName());
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new LoggingHandler(LogLevel.INFO));
}
});
ChannelFuture f = b.bind(18080).sync();
f.channel().closeFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
//业务逻辑处理代码,此处省略...
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
logger.info(future.channel().toString() + " 链路关闭");
}
});
} finally {
// bossGroup.shutdownGracefully();
// workerGroup.shutdownGracefully();
}
}
}
5. 通过注册jvm退出钩子函数,进行处理退出前的逻辑Runtime.getRuntime().addShutdownHook();
import java.util.concurrent.TimeUnit;
public class Shutdown1 {
public static void main(String [] args) throws Exception
{
Runtime.getRuntime().addShutdownHook(new java.lang.Thread(()->
{
//3.此代码jvm退出之前会自动调用即执行System.exit(0)完调用下面语句
System.out.println(System.currentTimeMillis());
System.out.println("ShutdownHook execute start...");
System.out.println("Netty NioEventLoopGroup shutdownGracefully...");
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ShutdownHook execute end...");
},""));
//1 先执行
System.out.println(System.currentTimeMillis() + "before");
TimeUnit.SECONDS.sleep(7);
System.out.println(System.currentTimeMillis());
//2. 执行此句,但没有真正的退出
System.exit(0);
//此句永远不会被执行
System.out.println("hello");
}
}
6. 通过linux 的kill -9 pid 或windows的tctrl + c来调用如下代码关闭
import sun.misc.Signal;
import sun.misc.SignalHandler;
import java.util.concurrent.TimeUnit;
public class SignalHandlerTest {
public static void main(String [] args) throws Exception
{
String signal = System.getProperties().getProperty("os.name").toLowerCase().startsWith("win") ? "INT" : "TERM";
System.out.println(System.getProperties().getProperty("os.name").toLowerCase());
Signal sig = new Signal("INT");//以windows操作系统为例
Signal.handle(sig, (s)->{
//执行kill -9 pid 或windows的tctrl + c后执行如下代码
System.out.println("Signal handle start...");
try {
// TimeUnit.SECONDS.sleep(Integer.MAX_VALUE); //如果阻塞后,后面钩子函数不会执行
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Runtime.getRuntime().addShutdownHook(new Thread(()->
{
System.out.println("ShutdownHook execute start...");
System.out.println("Netty NioEventLoopGroup shutdownGracefully...");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ShutdownHook execute end...");
},""));
new Thread(new Runnable() {
public void run() {
try {
TimeUnit.DAYS.sleep(Long.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();}}
}, "Daemon-T").start();
}
}