diff --git a/pom.xml b/pom.xml index 3ce17a8..4077b45 100644 --- a/pom.xml +++ b/pom.xml @@ -1,29 +1,47 @@ - - 4.0.0 - JavaCore - JavaCore - 0.0.1-SNAPSHOT + + 4.0.0 + JavaCore + JavaCore + 0.0.1-SNAPSHOT junit junit - 3.8.1 - test + 4.12 + + + + redis.clients + jedis + 2.1.0 + + + + commons-pool + commons-pool + 1.6 + + + + io.netty + netty-all + 5.0.0.Alpha2 - - src - - - maven-compiler-plugin - 3.1 - - 1.7 - 1.7 - - - - + + src + + + maven-compiler-plugin + 3.1 + + 1.7 + 1.7 + + + + \ No newline at end of file diff --git a/src/main/java/com/JVM/heap/HeapGCTest.java b/src/main/java/com/JVM/heap/HeapGCTest.java new file mode 100644 index 0000000..4d975c2 --- /dev/null +++ b/src/main/java/com/JVM/heap/HeapGCTest.java @@ -0,0 +1,18 @@ +package com.ufclub.ljs.autoInvest.model.AutoInvestSettingcom.JVM.heap; + +/** + * Java GC测试 + * @author chenssy + * @date 2016年11月19日 + * @since v1.0.0 + */ +public class HeapGCTest { + //VM参数:-Xms=40 -Xmx40m -Xmn20m + public static void main(String[] args){ + byte[] b1 = new byte[1024 * 1024 / 2]; + byte[] b2 = new byte[2014 * 1024 * 8]; + + b2 = null; + b2 = new byte[2014 * 1024 * 8]; + } +} diff --git a/src/main/java/com/JVM/perm/PermGengc.java b/src/main/java/com/JVM/perm/PermGengc.java new file mode 100644 index 0000000..d1fb6e5 --- /dev/null +++ b/src/main/java/com/JVM/perm/PermGengc.java @@ -0,0 +1,16 @@ +package com.ufclub.ljs.autoInvest.model.AutoInvestSettingcom.JVM.perm; + +/** + * 常量池GC策略:只要常量池中的常量没有被任何地方引用,就可以被回收 + * @author chenssy + * @date 2016年11月19日 + * @since v1.0.0 + */ +public class PermGengc { + + public static void main(String[] args){ + for(int i = 0 ; i < Integer.MAX_VALUE ; i++){ + String t = String.valueOf(i).intern(); + } + } +} diff --git a/src/main/java/com/JVM/stack/StackGCTest.java b/src/main/java/com/JVM/stack/StackGCTest.java new file mode 100644 index 0000000..98efc49 --- /dev/null +++ b/src/main/java/com/JVM/stack/StackGCTest.java @@ -0,0 +1,45 @@ +package com.ufclub.ljs.autoInvest.model.AutoInvestSettingcom.JVM.stack; + +/** + * @author chenssy + * @date 2016/11/19 + * @since v1.0.0 + */ +public class StackGCTest { + + //如果一个局部变量被保存在局部变量表中,那么GC就能引用到这个局部变量所指向的内存空间 + //从而在GC时,可能无法回收这部分空间 + public static void test1(){ + { + byte[] bytes = new byte[6 * 1024 * 1024]; + } + System.gc(); + System.out.println("first explict gc over"); + } + + //手工释放该空间,将变量设置为null + public static void test2(){ + { + byte[] bytes = new byte[6 * 1024 * 1024]; + bytes = null; + } + System.gc(); + System.out.println("first explict gc over"); + } + + //或者重新声明一个新的局部变量,从而复用该变量的字,使其所占有的空间可以被GC回收 + public static void test3(){ + { + byte[] bytes = new byte[6 * 1024 * 1024]; + } + int a = 0; + System.gc(); + System.out.println("first explict gc over"); + } + + + public static void main(String[] args){ + test1(); +// test2(); + } +} diff --git a/src/main/java/com/JVM/stack/TestStack.java b/src/main/java/com/JVM/stack/TestStack.java new file mode 100644 index 0000000..c914b34 --- /dev/null +++ b/src/main/java/com/JVM/stack/TestStack.java @@ -0,0 +1,30 @@ +package com.JVM.stack; + +import org.junit.Test; + +/** + * 测试当前栈的深度 + * + * @author chenssy + * @date 2016-11-15 + * @since v1.0.0 + */ +public class TestStack { + private int count = 0; + + public void recursion(){ + count++; + recursion(); + } + + @Test + public void testStack(){ + try { + recursion(); + } catch (Throwable e) { + System.out.println("Deep of stack is " + count); + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/com/JVM/stack/WordReuseTest.java b/src/main/java/com/JVM/stack/WordReuseTest.java new file mode 100644 index 0000000..0515a7e --- /dev/null +++ b/src/main/java/com/JVM/stack/WordReuseTest.java @@ -0,0 +1,23 @@ +package com.JVM.stack; + +/** + * 局部变量对GC的影响; + * + * + * @author chenssy + * @date 2016-11-17 + * @since v1.0.0 + */ +public class WordReuseTest { + public static void test(){ + { + byte[] b = new byte[6 * 1024 * 1024]; + } + System.gc(); + System.out.println("first explict gc over"); + } + + public static void main(String[] args){ + test(); + } +} diff --git a/src/main/java/com/NIO/core/BufferTest.java b/src/main/java/com/NIO/core/BufferTest.java new file mode 100644 index 0000000..ff27740 --- /dev/null +++ b/src/main/java/com/NIO/core/BufferTest.java @@ -0,0 +1,41 @@ +package com.NIO.core; + +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; + +/** + * Buffer测试
+ * buffer使用步骤: + * 1、写入数据到Buffer + * 2、调用flip()方法 + * 3、从Buffer中读取数据 + * 4、调用clear()方法或者compact()方法 + * + * @author chenming + * @date 2016年11月21日 + * @since v1.0.0 + */ +public class BufferTest { + public static void main(String[] args) throws Exception { + RandomAccessFile file = new RandomAccessFile("E:/workspace/channelTest.txt","rw"); + + FileChannel fileChannel = file.getChannel(); + + //对buffer对象进行分配 + ByteBuffer buf = ByteBuffer.allocate(24); + + int bytesRead = fileChannel.read(buf); + while (bytesRead != -1){ + buf.flip(); //切换到读模式 + while (buf.hasRemaining()){ + System.out.println((char)buf.get()); + } + + buf.clear(); //清空缓存 + bytesRead = fileChannel.read(buf); + } + + file.close(); + } +} diff --git a/src/main/java/com/NIO/core/ChannelTest.java b/src/main/java/com/NIO/core/ChannelTest.java new file mode 100644 index 0000000..cdaebf9 --- /dev/null +++ b/src/main/java/com/NIO/core/ChannelTest.java @@ -0,0 +1,29 @@ +package com.NIO.core; + +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; + +public class ChannelTest { + public static void main(String[] args) throws Exception { + RandomAccessFile file = new RandomAccessFile("E:/workspace/channelTest.txt","rw"); + + FileChannel fileChannel = file.getChannel(); + + ByteBuffer buf = ByteBuffer.allocate(8); + + int bytesRead = fileChannel.read(buf); + while (bytesRead != -1){ + System.out.println("Read " + bytesRead); + buf.flip(); + while (buf.hasRemaining()){ + System.out.println((char)buf.get()); + } + + buf.clear(); + bytesRead = fileChannel.read(buf); + } + + file.close(); + } +} diff --git a/src/main/java/com/NIO/netty/Http/fileServer/HttpFileServer.java b/src/main/java/com/NIO/netty/Http/fileServer/HttpFileServer.java new file mode 100644 index 0000000..435a6e8 --- /dev/null +++ b/src/main/java/com/NIO/netty/Http/fileServer/HttpFileServer.java @@ -0,0 +1,50 @@ +package com.NIO.netty.Http.fileServer; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpRequestDecoder; +import io.netty.handler.codec.http.HttpResponseEncoder; +import io.netty.handler.stream.ChunkedWriteHandler; + +public class HttpFileServer { + private static final String DEFAULT_URL = "/src/main/java/come/NIO/netty"; + + public void run(int port, final String url) throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + EventLoopGroup workerGroup = new NioEventLoopGroup(); + + try{ + ServerBootstrap sb = new ServerBootstrap(); + sb.group(bossGroup,workerGroup) + .channel(NioServerSocketChannel.class) + .childHandler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + socketChannel.pipeline().addLast("http-decoder",new HttpRequestDecoder()); + socketChannel.pipeline().addLast("http-aggregator",new HttpObjectAggregator(65536)); + socketChannel.pipeline().addLast("http-encoder",new HttpResponseEncoder()); + socketChannel.pipeline().addLast("http-chunked",new ChunkedWriteHandler()); + socketChannel.pipeline().addLast("fileServerHandler",new HttpFileServerHandler(url)); + } + }); + + ChannelFuture future = sb.bind("127.0.0.1",port); + System.out.println("HTTP 文件目录服务器启动,网址是:http://127.0.0.1"); + + future.channel().closeFuture().sync(); + }finally { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } + + public static void main(String[] args) throws Exception { + new HttpFileServer().run(8999,"127.0.0.1"); + } +} diff --git a/src/main/java/com/NIO/netty/Http/fileServer/HttpFileServerHandler.java b/src/main/java/com/NIO/netty/Http/fileServer/HttpFileServerHandler.java new file mode 100644 index 0000000..23dde24 --- /dev/null +++ b/src/main/java/com/NIO/netty/Http/fileServer/HttpFileServerHandler.java @@ -0,0 +1,16 @@ +package com.NIO.netty.Http.fileServer; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; + +public class HttpFileServerHandler extends SimpleChannelInboundHandler{ + public HttpFileServerHandler(String url) { + + } + + @Override + protected void messageReceived(ChannelHandlerContext channelHandlerContext, FullHttpRequest fullHttpRequest) throws Exception { + + } +} diff --git a/src/main/java/com/NIO/netty/base/TimeClient.java b/src/main/java/com/NIO/netty/base/TimeClient.java new file mode 100644 index 0000000..e3519a0 --- /dev/null +++ b/src/main/java/com/NIO/netty/base/TimeClient.java @@ -0,0 +1,44 @@ +package com.NIO.netty.base; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.*; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; + +public class TimeClient { + + public void connect(int port, String host) { + // 配置客户端线程组 + EventLoopGroup group = new NioEventLoopGroup(); + + Bootstrap b = new Bootstrap(); + + try { + b.group(group).channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + socketChannel.pipeline().addLast(new TimeClientHandler()); + } + }); + + // 发起异步连接操作 + ChannelFuture future = b.connect(host, port); + + // 等待客户端链路关闭 + + + future.channel().closeFuture().sync(); + } catch (InterruptedException e) { + + } finally { + group.shutdownGracefully(); + } + } + + public static void main(String[] args) { + new TimeClient().connect(8899,"127.0.0.1"); + } +} diff --git a/src/main/java/com/NIO/netty/base/TimeClientHandler.java b/src/main/java/com/NIO/netty/base/TimeClientHandler.java new file mode 100644 index 0000000..5fc2c53 --- /dev/null +++ b/src/main/java/com/NIO/netty/base/TimeClientHandler.java @@ -0,0 +1,45 @@ +package com.NIO.netty.base; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerAdapter; +import io.netty.channel.ChannelHandlerContext; + +public class TimeClientHandler extends ChannelHandlerAdapter{ + + private final ByteBuf firstMessage; + + public TimeClientHandler(){ + byte[] req = "QUERY TIME ORDER".getBytes(); + firstMessage = Unpooled.buffer(req.length); + + firstMessage.writeBytes(req); + } + + + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + ctx.writeAndFlush(firstMessage); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + ByteBuf buf = (ByteBuf) msg; + + byte[] req = new byte[buf.readableBytes()]; + buf.readBytes(req); + + String body = new String(req,"UTF-8"); + + System.out.println("Now is :" + body); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + + System.out.println("cause by :" + cause.getMessage()); + + ctx.close(); + } +} diff --git a/src/main/java/com/NIO/netty/base/TimeServer.java b/src/main/java/com/NIO/netty/base/TimeServer.java new file mode 100644 index 0000000..428a541 --- /dev/null +++ b/src/main/java/com/NIO/netty/base/TimeServer.java @@ -0,0 +1,52 @@ +package com.NIO.netty.base; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; + +public class TimeServer { + + public void bind(int port){ + // 配置服务端的NIO线程组 + EventLoopGroup bossGroup = new NioEventLoopGroup(); // 用于服务端接受客户端的连接 + EventLoopGroup workerGroup = new NioEventLoopGroup(); // 用于进行SocketChannel的网络读写 + + try { + // ServerBootstrap 用于启动NIO服务端的辅助启动类,目的是降低服务端的开发复杂度 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .option(ChannelOption.SO_BACKLOG, 1024) + .childHandler(new ChildChannelHanlder()); + + // 绑定端口,同步等待成功 + ChannelFuture future = b.bind(port).sync(); + // 等待服务端监听端口关闭 + future.channel().closeFuture().sync(); + + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + // 优雅地关闭 + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } + + private class ChildChannelHanlder extends ChannelInitializer{ + + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + socketChannel.pipeline().addLast(new TimerServerHandler()); + } + } + + public static void main(String[] args){ + new TimeServer().bind(8899); + } +} diff --git a/src/main/java/com/NIO/netty/base/TimerServerHandler.java b/src/main/java/com/NIO/netty/base/TimerServerHandler.java new file mode 100644 index 0000000..5ee15b9 --- /dev/null +++ b/src/main/java/com/NIO/netty/base/TimerServerHandler.java @@ -0,0 +1,39 @@ +package com.NIO.netty.base; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerAdapter; +import io.netty.channel.ChannelHandlerContext; + +import java.util.Date; + + +public class TimerServerHandler extends ChannelHandlerAdapter{ + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + ByteBuf buf = (ByteBuf) msg; + + byte[] req = new byte[buf.readableBytes()]; + buf.readBytes(req); + + String body = new String(req,"UTF-8"); + System.out.println("The time server receive order:" + body); + + String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER"; + + ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes()); + + ctx.write(resp); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ctx.close(); + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } +} diff --git a/src/main/java/com/NIO/netty/frameDecoder/DelimiterBasedFrameDecoder/EchoClient.java b/src/main/java/com/NIO/netty/frameDecoder/DelimiterBasedFrameDecoder/EchoClient.java new file mode 100644 index 0000000..0256bee --- /dev/null +++ b/src/main/java/com/NIO/netty/frameDecoder/DelimiterBasedFrameDecoder/EchoClient.java @@ -0,0 +1,50 @@ +package com.NIO.netty.frameDecoder.DelimiterBasedFrameDecoder; + +import io.netty.bootstrap.Bootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.DelimiterBasedFrameDecoder; +import io.netty.handler.codec.string.StringDecoder; + +public class EchoClient { + public void connect(int port,String host) throws Exception { + EventLoopGroup group = new NioEventLoopGroup(); + + try { + Bootstrap sb = new Bootstrap(); + sb.group(group).channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes()); + + socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter)); + + socketChannel.pipeline().addLast(new StringDecoder()); + + socketChannel.pipeline().addLast(new EchoClientHandler()); + } + }); + + ChannelFuture f = sb.connect(host,port).sync(); + + f.channel().closeFuture().sync(); + } finally { + group.shutdownGracefully(); + } + } + + public static void main(String[] args) throws Exception { + new EchoClient().connect(8999,"127.0.0.1"); + } + + +} diff --git a/src/main/java/com/NIO/netty/frameDecoder/DelimiterBasedFrameDecoder/EchoClientHandler.java b/src/main/java/com/NIO/netty/frameDecoder/DelimiterBasedFrameDecoder/EchoClientHandler.java new file mode 100644 index 0000000..bcd3434 --- /dev/null +++ b/src/main/java/com/NIO/netty/frameDecoder/DelimiterBasedFrameDecoder/EchoClientHandler.java @@ -0,0 +1,35 @@ +package com.NIO.netty.frameDecoder.DelimiterBasedFrameDecoder; + +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerAdapter; +import io.netty.channel.ChannelHandlerContext; + +public class EchoClientHandler extends ChannelHandlerAdapter{ + private int counter; + + // 末尾增加$_ + static final String ECHO_REQ = "Hi,chenssy,welcome to netty.$_"; + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + for(int i = 0 ; i < 10 ; i++){ + ctx.writeAndFlush(Unpooled.copiedBuffer(ECHO_REQ.getBytes())); + } + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + System.out.println("This is " + (++counter) + " times receive server:[" + msg + "]"); + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + cause.printStackTrace(); + ctx.close(); + } +} diff --git a/src/main/java/com/NIO/netty/frameDecoder/DelimiterBasedFrameDecoder/EchoServer.java b/src/main/java/com/NIO/netty/frameDecoder/DelimiterBasedFrameDecoder/EchoServer.java new file mode 100644 index 0000000..dab9ff6 --- /dev/null +++ b/src/main/java/com/NIO/netty/frameDecoder/DelimiterBasedFrameDecoder/EchoServer.java @@ -0,0 +1,58 @@ +package com.NIO.netty.frameDecoder.DelimiterBasedFrameDecoder; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +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.codec.DelimiterBasedFrameDecoder; +import io.netty.handler.codec.string.StringDecoder; + +/** + * DelimiterBasedFrameDecoder 服务端 + * + * @author chenssy + * @date 2017-05-08 + * @since v1.0.0 + */ +public class EchoServer { + + public void bind(int port) throws Exception { + // 配置线程组 + EventLoopGroup boosGroup = new NioEventLoopGroup(); + EventLoopGroup workerGroup = new NioEventLoopGroup(); + + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.group(boosGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .option(ChannelOption.SO_BACKLOG, 100) + .childHandler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel channel) throws Exception { + ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes()); + channel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter)); + + channel.pipeline().addLast(new StringDecoder()); + channel.pipeline().addLast(new EchoServerHandler()); + } + }); + + //绑定端口 + ChannelFuture f = sb.bind(port).sync(); + + //等待服务端监听端口关闭 + f.channel().closeFuture().sync(); + } finally { + boosGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } + + public static void main(String[] args) throws Exception { + new EchoServer().bind(8999); + } + +} diff --git a/src/main/java/com/NIO/netty/frameDecoder/DelimiterBasedFrameDecoder/EchoServerHandler.java b/src/main/java/com/NIO/netty/frameDecoder/DelimiterBasedFrameDecoder/EchoServerHandler.java new file mode 100644 index 0000000..4bfca85 --- /dev/null +++ b/src/main/java/com/NIO/netty/frameDecoder/DelimiterBasedFrameDecoder/EchoServerHandler.java @@ -0,0 +1,32 @@ +package com.NIO.netty.frameDecoder.DelimiterBasedFrameDecoder; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerAdapter; +import io.netty.channel.ChannelHandlerContext; + +public class EchoServerHandler extends ChannelHandlerAdapter{ + + private int counter = 0; + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + String body = (String) msg; + + System.out.println("This is " + (++counter) + " times reveive client:[" + body + "]"); + + if(counter % 3 == 0){ + body += "$_"; + } + + ByteBuf buf = Unpooled.copiedBuffer(body.getBytes()); + + ctx.writeAndFlush(buf); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + cause.printStackTrace(); + ctx.close(); + } +} diff --git a/src/main/java/com/NIO/netty/frameDecoder/FixedLengthFrameDecoder/EchoServer.java b/src/main/java/com/NIO/netty/frameDecoder/FixedLengthFrameDecoder/EchoServer.java new file mode 100644 index 0000000..d566b4e --- /dev/null +++ b/src/main/java/com/NIO/netty/frameDecoder/FixedLengthFrameDecoder/EchoServer.java @@ -0,0 +1,61 @@ +package com.NIO.netty.frameDecoder.FixedLengthFrameDecoder; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.DelimiterBasedFrameDecoder; +import io.netty.handler.codec.FixedLengthFrameDecoder; +import io.netty.handler.codec.string.StringDecoder; + +/** + * DelimiterBasedFrameDecoder 服务端 + * + * @author chenssy + * @date 2017年05月08日 + * @since v1.0.0 + */ +public class EchoServer { + + public void bind(int port) throws Exception { + // 配置线程组 + EventLoopGroup boosGroup = new NioEventLoopGroup(); + EventLoopGroup workerGroup = new NioEventLoopGroup(); + + try { + ServerBootstrap sb = new ServerBootstrap(); + sb.group(boosGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .option(ChannelOption.SO_BACKLOG, 100) + .childHandler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel channel) throws Exception { + channel.pipeline().addLast(new FixedLengthFrameDecoder(20)); + + channel.pipeline().addLast(new StringDecoder()); + channel.pipeline().addLast(new EchoServerHandler()); + } + }); + + //绑定端口 + ChannelFuture f = sb.bind(port).sync(); + + //等待服务端监听端口关闭 + f.channel().closeFuture().sync(); + } finally { + boosGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } + + public static void main(String[] args) throws Exception { + new EchoServer().bind(8999); + } + +} diff --git a/src/main/java/com/NIO/netty/frameDecoder/FixedLengthFrameDecoder/EchoServerHandler.java b/src/main/java/com/NIO/netty/frameDecoder/FixedLengthFrameDecoder/EchoServerHandler.java new file mode 100644 index 0000000..f56f605 --- /dev/null +++ b/src/main/java/com/NIO/netty/frameDecoder/FixedLengthFrameDecoder/EchoServerHandler.java @@ -0,0 +1,26 @@ +package com.NIO.netty.frameDecoder.FixedLengthFrameDecoder; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerAdapter; +import io.netty.channel.ChannelHandlerContext; + +public class EchoServerHandler extends ChannelHandlerAdapter{ + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + String body = (String) msg; + + System.out.println("Receive client : [" + body + "]"); + + ByteBuf buf = Unpooled.copiedBuffer(body.getBytes()); + + ctx.writeAndFlush(buf); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + cause.printStackTrace(); + ctx.close(); + } +} diff --git a/src/main/java/com/NIO/netty/tcpIP/NotStickers/TimeClient.java b/src/main/java/com/NIO/netty/tcpIP/NotStickers/TimeClient.java new file mode 100644 index 0000000..867e2d5 --- /dev/null +++ b/src/main/java/com/NIO/netty/tcpIP/NotStickers/TimeClient.java @@ -0,0 +1,46 @@ +package com.NIO.netty.tcpIP.NotStickers; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; + +public class TimeClient { + + public void connect(int port, String host) { + // 配置客户端线程组 + EventLoopGroup group = new NioEventLoopGroup(); + + Bootstrap b = new Bootstrap(); + + try { + b.group(group).channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + socketChannel.pipeline().addLast(new TimeClientHandler()); + } + }); + + // 发起异步连接操作 + ChannelFuture future = b.connect(host, port); + + // 等待客户端链路关闭 + + future.channel().closeFuture().sync(); + } catch (InterruptedException e) { + + } finally { + group.shutdownGracefully(); + } + } + + public static void main(String[] args) { + new TimeClient().connect(8899,"127.0.0.1"); + } +} diff --git a/src/main/java/com/NIO/netty/tcpIP/NotStickers/TimeClientHandler.java b/src/main/java/com/NIO/netty/tcpIP/NotStickers/TimeClientHandler.java new file mode 100644 index 0000000..0e5fdcf --- /dev/null +++ b/src/main/java/com/NIO/netty/tcpIP/NotStickers/TimeClientHandler.java @@ -0,0 +1,52 @@ +package com.NIO.netty.tcpIP.NotStickers; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerAdapter; +import io.netty.channel.ChannelHandlerContext; + +public class TimeClientHandler extends ChannelHandlerAdapter{ + + private int counter; + + private byte[] req; + + + public TimeClientHandler(){ + req = ("QUERY TIME ORDER" + System.getProperty("line.separator")).getBytes(); + } + + + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + ByteBuf message = null; + + for (int i = 0 ; i < 100 ; i++){ + message = Unpooled.buffer(req.length); + message.writeBytes(req); + + ctx.writeAndFlush(message); + } + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + ByteBuf buf = (ByteBuf) msg; + + byte[] req = new byte[buf.readableBytes()]; + buf.readBytes(req); + + String body = new String(req,"UTF-8"); + + System.out.println("Now is :" + body + "; the conters is :" + (++counter)); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + + System.out.println("cause by :" + cause.getMessage()); + + ctx.close(); + } +} diff --git a/src/main/java/com/NIO/netty/tcpIP/NotStickers/TimeServer.java b/src/main/java/com/NIO/netty/tcpIP/NotStickers/TimeServer.java new file mode 100644 index 0000000..46b12f0 --- /dev/null +++ b/src/main/java/com/NIO/netty/tcpIP/NotStickers/TimeServer.java @@ -0,0 +1,52 @@ +package com.NIO.netty.tcpIP.NotStickers; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; + +public class TimeServer { + + public void bind(int port){ + // 配置服务端的NIO线程组 + EventLoopGroup bossGroup = new NioEventLoopGroup(); // 用于服务端接受客户端的连接 + EventLoopGroup workerGroup = new NioEventLoopGroup(); // 用于进行SocketChannel的网络读写 + + try { + // ServerBootstrap 用于启动NIO服务端的辅助启动类,目的是降低服务端的开发复杂度 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .option(ChannelOption.SO_BACKLOG, 1024) + .childHandler(new ChildChannelHanlder()); + + // 绑定端口,同步等待成功 + ChannelFuture future = b.bind(port).sync(); + // 等待服务端监听端口关闭 + future.channel().closeFuture().sync(); + + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + // 优雅地关闭 + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } + + private class ChildChannelHanlder extends ChannelInitializer{ + + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + socketChannel.pipeline().addLast(new TimerServerHandler()); + } + } + + public static void main(String[] args){ + new TimeServer().bind(8899); + } +} diff --git a/src/main/java/com/NIO/netty/tcpIP/NotStickers/TimerServerHandler.java b/src/main/java/com/NIO/netty/tcpIP/NotStickers/TimerServerHandler.java new file mode 100644 index 0000000..a3460cc --- /dev/null +++ b/src/main/java/com/NIO/netty/tcpIP/NotStickers/TimerServerHandler.java @@ -0,0 +1,45 @@ +package com.NIO.netty.tcpIP.NotStickers; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerAdapter; +import io.netty.channel.ChannelHandlerContext; + +import java.util.Date; + +/** + * 未考虑粘包拆包 + * + * @author chenssy + * @date 2017年05月05日 + * @since v1.0.0 + */ +public class TimerServerHandler extends ChannelHandlerAdapter{ + + private int counter; + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + ByteBuf buf = (ByteBuf) msg; + + byte[] req = new byte[buf.readableBytes()]; + buf.readBytes(req); + + String body = new String(req,"UTF-8").substring(0,req.length - System.getProperty("line.separator").length()); + + System.out.println("The time server receive order:" + body + "; the counter is " + (++counter)); + + String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER"; + + currentTime = currentTime + System.getProperty("line.separator"); + + ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes()); + + ctx.writeAndFlush(resp); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ctx.close(); + } +} diff --git a/src/main/java/com/NIO/netty/tcpIP/stickers/TimeClient.java b/src/main/java/com/NIO/netty/tcpIP/stickers/TimeClient.java new file mode 100644 index 0000000..9c841a0 --- /dev/null +++ b/src/main/java/com/NIO/netty/tcpIP/stickers/TimeClient.java @@ -0,0 +1,50 @@ +package com.NIO.netty.tcpIP.stickers; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.LineBasedFrameDecoder; +import io.netty.handler.codec.string.StringDecoder; + +public class TimeClient { + + public void connect(int port, String host) { + // 配置客户端线程组 + EventLoopGroup group = new NioEventLoopGroup(); + + Bootstrap b = new Bootstrap(); + + try { + b.group(group).channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + socketChannel.pipeline().addLast(new LineBasedFrameDecoder(1024)); + socketChannel.pipeline().addLast(new StringDecoder()); + socketChannel.pipeline().addLast(new TimeClientHandler()); + } + }); + + // 发起异步连接操作 + ChannelFuture future = b.connect(host, port); + + // 等待客户端链路关闭 + + future.channel().closeFuture().sync(); + } catch (InterruptedException e) { + + } finally { + group.shutdownGracefully(); + } + } + + public static void main(String[] args) { + new TimeClient().connect(8899,"127.0.0.1"); + } +} diff --git a/src/main/java/com/NIO/netty/tcpIP/stickers/TimeClientHandler.java b/src/main/java/com/NIO/netty/tcpIP/stickers/TimeClientHandler.java new file mode 100644 index 0000000..32cf920 --- /dev/null +++ b/src/main/java/com/NIO/netty/tcpIP/stickers/TimeClientHandler.java @@ -0,0 +1,49 @@ +package com.NIO.netty.tcpIP.stickers; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerAdapter; +import io.netty.channel.ChannelHandlerContext; + +public class TimeClientHandler extends ChannelHandlerAdapter{ + + private int counter; + + private byte[] req; + + + public TimeClientHandler(){ + req = ("QUERY TIME ORDER" + System.getProperty("line.separator")).getBytes(); + } + + + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + ByteBuf message = null; + + for (int i = 0 ; i < 100 ; i++){ + message = Unpooled.buffer(req.length); + message.writeBytes(req); + + ctx.writeAndFlush(message); + } + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + + + String body = (String) msg; + + System.out.println("Now is :" + body + "; the conters is :" + (++counter)); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + + System.out.println("cause by :" + cause.getMessage()); + + ctx.close(); + } +} diff --git a/src/main/java/com/NIO/netty/tcpIP/stickers/TimeServer.java b/src/main/java/com/NIO/netty/tcpIP/stickers/TimeServer.java new file mode 100644 index 0000000..40fe4d1 --- /dev/null +++ b/src/main/java/com/NIO/netty/tcpIP/stickers/TimeServer.java @@ -0,0 +1,61 @@ +package com.NIO.netty.tcpIP.stickers; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.LineBasedFrameDecoder; +import io.netty.handler.codec.string.StringDecoder; + + +public class TimeServer { + + public void bind(int port){ + // 配置服务端的NIO线程组 + EventLoopGroup bossGroup = new NioEventLoopGroup(); // 用于服务端接受客户端的连接 + EventLoopGroup workerGroup = new NioEventLoopGroup(); // 用于进行SocketChannel的网络读写 + + try { + // ServerBootstrap 用于启动NIO服务端的辅助启动类,目的是降低服务端的开发复杂度 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .option(ChannelOption.SO_BACKLOG, 1024) + .childHandler(new ChildChannelHanlder()); + + // 绑定端口,同步等待成功 + ChannelFuture future = b.bind(port).sync(); + // 等待服务端监听端口关闭 + future.channel().closeFuture().sync(); + + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + // 优雅地关闭 + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } + + private class ChildChannelHanlder extends ChannelInitializer{ + + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + + // 解码器 + socketChannel.pipeline().addLast(new LineBasedFrameDecoder(1024)); + socketChannel.pipeline().addLast(new StringDecoder()); + + // 服务处理 + socketChannel.pipeline().addLast(new TimerServerHandler()); + } + } + + public static void main(String[] args){ + new TimeServer().bind(8899); + } +} diff --git a/src/main/java/com/NIO/netty/tcpIP/stickers/TimerServerHandler.java b/src/main/java/com/NIO/netty/tcpIP/stickers/TimerServerHandler.java new file mode 100644 index 0000000..d12f329 --- /dev/null +++ b/src/main/java/com/NIO/netty/tcpIP/stickers/TimerServerHandler.java @@ -0,0 +1,40 @@ +package com.NIO.netty.tcpIP.stickers; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerAdapter; +import io.netty.channel.ChannelHandlerContext; + +import java.util.Date; + +/** + * 未考虑粘包拆包 + * + * @author chenssy + * @date 2017年05月05日 + * @since v1.0.0 + */ +public class TimerServerHandler extends ChannelHandlerAdapter{ + + private int counter; + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + String body = (String) msg; + + System.out.println("The time server receive order:" + body + "; the counter is :" + (++counter)); + + String currentTime = " QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER"; + + currentTime = currentTime + System.getProperty("line.separator"); + + ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes()); + + ctx.writeAndFlush(resp); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ctx.close(); + } +} diff --git a/src/main/java/com/NIO/nio/_1/MultiplexerTimerServer.java b/src/main/java/com/NIO/nio/_1/MultiplexerTimerServer.java new file mode 100644 index 0000000..d5625aa --- /dev/null +++ b/src/main/java/com/NIO/nio/_1/MultiplexerTimerServer.java @@ -0,0 +1,162 @@ +package com.NIO.nio._1; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.Date; +import java.util.Iterator; +import java.util.Set; + +/** + * 服务器端 + * + * @author chenssy + * @date 2017年04月20日 + * @since v1.0.0 + */ +public class MultiplexerTimerServer implements Runnable{ + + // 多路复用器 + private Selector selector; + + // 通道 + private ServerSocketChannel serverSocketChannel; + + private volatile boolean stop; + + MultiplexerTimerServer(int port){ + try { + // 打开通道channel,监听客户端连接 + selector = Selector.open(); + + serverSocketChannel = ServerSocketChannel.open(); + //监听端口 + serverSocketChannel.socket().bind(new InetSocketAddress(port),1024); + // 设置为非阻塞 + serverSocketChannel.configureBlocking(false); + + //将通道channel注册到多路复用器selector上面 + serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); + + System.out.println("The time server is start in port:" + port); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void stop(){ + this.stop = true; + } + + @Override + public void run() { + while (!stop){ + try { + selector.select(1000); + + Set selectionKeys = selector.selectedKeys(); + Iterator it = selectionKeys.iterator(); + + SelectionKey key = null; + + while (it.hasNext()){ + key = it.next(); + + it.remove(); + + try { + handleInput(key); + } catch (IOException e) { + if(key != null){ + key.cancel(); + if(key.channel() != null){ + key.channel().close(); + } + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + // 多路复用器关闭后,所有注册在上面的Channel等资源都会自动去注册并关闭,所以不需要重复释放资源 + if(selector != null){ + try { + selector.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * 处理链接请求 + * + * @author chenssy + * @date 2017年04月20日 + * @since v1.0.0 + */ + private void handleInput(SelectionKey key) throws IOException { + if(key.isValid()){ + // 处理新接入的请求 + if(key.isAcceptable()){ + ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); + + SocketChannel channel = ssc.accept(); + ssc.configureBlocking(false); + ssc.register(selector,SelectionKey.OP_READ); // 准备读 + } + + // 读取数据 + if(key.isReadable()){ + SocketChannel sc = (SocketChannel) key.channel(); + + ByteBuffer readBuffer = ByteBuffer.allocate(1024); + + int readBytes = sc.read(readBuffer); + + if(readBytes> 0){ + readBuffer.flip(); + + byte[] bytes = new byte[readBuffer.remaining()]; + + readBuffer.get(bytes); + String body = new String(bytes,"UTF-8"); + + System.out.println("The time server receive order:" + body); + String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER"; + + doWrite(sc,currentTime); + }else if(readBytes < 0){ + // 关闭终端 + key.cancel(); + sc.close(); + } + } + } + } + + /** + * 向客户端写入数据 + * + * @author chenssy + * @date 2017-04-20 + * @since v1.0.0 + */ + private void doWrite(SocketChannel channel, String response) throws IOException { + if(response != null && response.trim().length()> 0){ + byte[] bytes = response.getBytes(); + + ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length); + + writeBuffer.put(bytes); + writeBuffer.flip(); + channel.write(writeBuffer); + } + } +} diff --git a/src/main/java/com/NIO/nio/_1/TimeClientHandle.java b/src/main/java/com/NIO/nio/_1/TimeClientHandle.java new file mode 100644 index 0000000..c35f192 --- /dev/null +++ b/src/main/java/com/NIO/nio/_1/TimeClientHandle.java @@ -0,0 +1,82 @@ +package com.NIO.nio._1; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.SocketChannel; + +public class TimeClientHandle implements Runnable{ + private String host; + + private int port; + + private Selector selector; + + private SocketChannel socketChannel; + + private volatile boolean stop; + + public TimeClientHandle(String host,int port){ + this.host = host == null ? "127.0.0.1" : host; + this.port = port; + + try { + selector = Selector.open(); + socketChannel = SocketChannel.open(); + socketChannel.configureBlocking(false); + } catch (IOException e) { + e.printStackTrace(); + } + } + + + @Override + public void run() { + try { + doConnect(); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + /** + * 链接服务端 + * 如果链接成功,则注册到多路复用器上,发送请求消息,读应答 + * @author chenming + * @date 2017年04月20日 + * @since v1.0.0 + */ + private void doConnect() throws IOException { + if(socketChannel.connect(new InetSocketAddress(host,port))){ + socketChannel.register(selector, SelectionKey.OP_READ); + dowWrite(socketChannel); + }else{ + socketChannel.register(selector,SelectionKey.OP_CONNECT); + } + } + + /** + * 发送消息 + * + * @author chenming + * @date 2017年04月20日 + * @since v1.0.0 + */ + private void dowWrite(SocketChannel socketChannel) throws IOException { + byte[] req = "QUERY TIME ORDER".getBytes(); + + ByteBuffer writeBuffer = ByteBuffer.allocate(req.length); + + writeBuffer.put(req); + writeBuffer.flip(); + + socketChannel.write(writeBuffer); + + if(!writeBuffer.hasRemaining()){ + System.out.println("Send order 2 Server succeed."); + } + } +} diff --git a/src/main/java/com/javaCore/java_thread/JUC/Atomic/AtomicReferenceTest.java b/src/main/java/com/javaCore/java_thread/JUC/Atomic/AtomicReferenceTest.java index 52f8299..e5ed2c3 100644 --- a/src/main/java/com/javaCore/java_thread/JUC/Atomic/AtomicReferenceTest.java +++ b/src/main/java/com/javaCore/java_thread/JUC/Atomic/AtomicReferenceTest.java @@ -32,7 +32,7 @@ public String toString() { } } - private static AtomicReference atomicReference = new AtomicReference(); + private static AtomicReference atomicReference = new AtomicReference(); public static void main(String[] args){ User user = new User("chenssy",18); diff --git a/src/main/java/com/javaCore/java_thread/JUC/ThreadUtils/Exchanger/Test.java b/src/main/java/com/javaCore/java_thread/JUC/ThreadUtils/Exchanger/Test.java index 6a2aa21..636875a 100644 --- a/src/main/java/com/javaCore/java_thread/JUC/ThreadUtils/Exchanger/Test.java +++ b/src/main/java/com/javaCore/java_thread/JUC/ThreadUtils/Exchanger/Test.java @@ -6,10 +6,10 @@ public class Test { public static void main(String[] args) { - List buffer1 = new ArrayList(); - List buffer2 = new ArrayList(); + List buffer1 = new ArrayList(); + List buffer2 = new ArrayList(); - Exchanger> exchanger = new Exchanger(); + Exchanger> exchanger = new Exchanger>(); Producer producer = new Producer(buffer1, exchanger); Consumer consumer = new Consumer(buffer2, exchanger); diff --git a/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/ClientThread.java b/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/ClientThread.java new file mode 100644 index 0000000..f334e9f --- /dev/null +++ b/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/ClientThread.java @@ -0,0 +1,33 @@ +package com.javaCore.java_thread.model.GuardedSuspension; + +/** + * @Author: chenssy + * @Date: 2016年10月26日 22:30 + */ +public class ClientThread extends Thread{ + private RequestQueue requestQueue; + + public ClientThread(RequestQueue requestQueue ,String name){ + super(name); + this.requestQueue = requestQueue; + } + + @Override + public void run() { + for(int i = 0 ; i < 10 ; i++){ + Request request = new Request("RequestId:" + i + "ThreadName:" + Thread.currentThread().getName()); + System.out.println(Thread.currentThread().getName() + " request " + request); + + requestQueue.addRequest(request); //提交请求 + + try { + Thread.sleep(100); //客户端请求速度快于服务端处理速度 + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("ClientThread name is "+Thread.currentThread().getName()); + } + + System.out.println(Thread.currentThread().getName() + "request end"); + } +} diff --git a/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/Request.java b/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/Request.java new file mode 100644 index 0000000..c26e12c --- /dev/null +++ b/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/Request.java @@ -0,0 +1,18 @@ +package com.javaCore.java_thread.model.GuardedSuspension; + +/** + * @Author: chenssy + * @Date: 2016/10/26 22:13 + */ +public class Request { + private String name; + + public Request(String name){ + this.name = name; + } + + @Override + public String toString() { + return "[Request " + name + "]"; + } +} diff --git a/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/RequestQueue.java b/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/RequestQueue.java new file mode 100644 index 0000000..830e07c --- /dev/null +++ b/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/RequestQueue.java @@ -0,0 +1,31 @@ +package com.javaCore.java_thread.model.GuardedSuspension; + +import java.util.LinkedList; +import java.util.List; + +/** + * 维护Request请求信息 + * + * @Author: chenssy + * @Date: 2016/10/26 22:23 + */ +public class RequestQueue { + private LinkedList queue = new LinkedList(); + + public synchronized Request getRequest(){ + while(queue.size() == 0){ + try{ + wait(); //等待,直到有Request + }catch(InterruptedException e){ + + } + } + + return (Request) queue.remove(); + } + + public synchronized void addRequest(Request request){ + queue.add(request); + notifyAll(); //唤醒getRequest方法 + } +} diff --git a/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/ServerThread.java b/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/ServerThread.java new file mode 100644 index 0000000..25249cd --- /dev/null +++ b/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/ServerThread.java @@ -0,0 +1,28 @@ +package com.javaCore.java_thread.model.GuardedSuspension; + +/** + * @Author: chenssy + * @Date: 2016/10/26 22:27 + */ +public class ServerThread extends Thread{ + private RequestQueue requestQueue; + + public ServerThread(RequestQueue requestQueue,String name){ + super(name); + this.requestQueue = requestQueue; + } + + @Override + public void run() { + while(true){ + final Request request = requestQueue.getRequest(); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + + } + System.out.println(Thread.currentThread().getName() + " handles " + request); + } + } +} diff --git a/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/Test.java b/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/Test.java new file mode 100644 index 0000000..7837200 --- /dev/null +++ b/src/main/java/com/javaCore/java_thread/model/GuardedSuspension/Test.java @@ -0,0 +1,21 @@ +package com.javaCore.java_thread.model.GuardedSuspension; + +/** + * @Author: chenssy + * @Date: 2016/10/26 22:35 + */ +public class Test { + public static void main(String[] args){ + RequestQueue requestQueue = new RequestQueue(); + + //开启服务端进程 + for(int i = 0 ; i < 10 ; i++){ + new ServerThread(requestQueue,"ServerThread_" + i).start(); + } + + //开启客户端进程 + for(int i = 0 ; i < 10 ; i++){ + new ClientThread(requestQueue,"ClientThread_" + i).start(); + } + } +} diff --git a/src/main/java/com/javaCore/java_thread/model/MasterWorker/Master.java b/src/main/java/com/javaCore/java_thread/model/MasterWorker/Master.java new file mode 100644 index 0000000..8bb2a70 --- /dev/null +++ b/src/main/java/com/javaCore/java_thread/model/MasterWorker/Master.java @@ -0,0 +1,80 @@ +package com.javaCore.java_thread.model.MasterWorker; + +import java.util.HashMap; +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedDeque; + +/** + * @Author: chenssy + * @Date: 2016/10/26 21:03 + */ +public class Master { + //任务队列 + protected Queue workQueue = new ConcurrentLinkedDeque(); + //Work进程队列 + protected Map threadMap = new HashMap(); + //子任务处理结果集 + protected Map resultMap = new ConcurrentHashMap(); + + /** + * 判断任务是否结束 + * + * @author chenssy + * @date 2016年10月26日 + * @since v1.0.0 + */ + public boolean isComplete(){ + for(Map.Entry entry : threadMap.entrySet()){ + if(entry.getValue().getState() != Thread.State.TERMINATED){ + return false; + } + } + return true; + } + + public Master(Worker worker,int countWorker){ + worker.setWorkerQueue(workQueue); + worker.setResultMap(resultMap); + + for(int i = 0 ; i < countWorker ; i++){ + threadMap.put(Integer.toString(i),new Thread(worker,Integer.toString(i))); + } + } + + /** + * 提交一个任务 + * + * @author chenssy + * @date 2016-10-26 + * @since v1.0.0 + */ + public void submit(Object object){ + workQueue.add(object); + } + + /** + * 获取结果集 + * + * @author chenssy + * @date 2016-10-26 + * @since v1.0.0 + */ + public Map getResultMap(){ + return resultMap; + } + + /** + * 执行子任务 + * + * @author chenssy + * @date 2016年10月26日 + * @since v1.0.0 + */ + public void execute(){ + for (Map.Entry entery:threadMap.entrySet()){ + entery.getValue().start(); + } + } +} diff --git a/src/main/java/com/javaCore/java_thread/model/MasterWorker/PlusWorker.java b/src/main/java/com/javaCore/java_thread/model/MasterWorker/PlusWorker.java new file mode 100644 index 0000000..931448b --- /dev/null +++ b/src/main/java/com/javaCore/java_thread/model/MasterWorker/PlusWorker.java @@ -0,0 +1,13 @@ +package com.javaCore.java_thread.model.MasterWorker; + +/** + * @Author: chenssy + * @Date: 2016年10月26日 21:25 + */ +public class PlusWorker extends Worker { + @Override + public Object handle(Object input) { + Integer i = (Integer) input; + return i * i * i; + } +} diff --git a/src/main/java/com/javaCore/java_thread/model/MasterWorker/Test.java b/src/main/java/com/javaCore/java_thread/model/MasterWorker/Test.java new file mode 100644 index 0000000..4d7f8c8 --- /dev/null +++ b/src/main/java/com/javaCore/java_thread/model/MasterWorker/Test.java @@ -0,0 +1,48 @@ +package com.javaCore.java_thread.model.MasterWorker; + +import java.util.Map; +import java.util.Set; + +/** + * @Author: chenssy + * @Date: 2016年10月26日 21:32 + */ +public class Test { + public static void main(String[] args){ + //五个进程跑 + Master master = new Master(new PlusWorker(),5); + + //提交100个子任务 + for(int i = 0 ; i < 100 ; i++){ + master.submit(i); + } + + master.execute(); + + int result = 0 ; + + Map resultMap = master.getResultMap(); + + while(resultMap.size()> 0 || !master.isComplete()){ + Set keys = resultMap.keySet(); + String key = null; + for(String s : keys){ + key = s; + break; + } + + Integer i = null; + + if(key != null){ + i = (Integer) resultMap.get(key); + } + if(i != null){ + result += i; + } + + if(key != null){ + resultMap.remove(key); + } + } + } +} diff --git a/src/main/java/com/javaCore/java_thread/model/MasterWorker/Worker.java b/src/main/java/com/javaCore/java_thread/model/MasterWorker/Worker.java new file mode 100644 index 0000000..b719783 --- /dev/null +++ b/src/main/java/com/javaCore/java_thread/model/MasterWorker/Worker.java @@ -0,0 +1,48 @@ +package com.javaCore.java_thread.model.MasterWorker; + +import java.util.Map; +import java.util.Queue; + +/** + * @Author: chenssy + * @Date: 2016年10月26日 21:15 + */ +public class Worker implements Runnable{ + protected Queue workerQueue; + + protected Map resultMap ; + + public void setWorkerQueue(Queue workerQueue) { + this.workerQueue = workerQueue; + } + + public void setResultMap(Map resultMap) { + this.resultMap = resultMap; + } + + @Override + public void run() { + while (true){ + Object input = workerQueue.poll(); + if(input == null){ + break; + } + + System.out.println("子任务【" + Thread.currentThread().getName() + "】开始执行,执行对象为--" + input.toString()); + Object result = handle(input); + System.out.println("子任务【" + Thread.currentThread().getName() + "】执行完成,结果为:" + result.toString()); + resultMap.put(Integer.toString(input.hashCode()),result); + } + } + + /** + * 子任务处理逻辑,在子类中覆盖执行具体逻辑 + * + * @author chenssy + * @date 2016年10月26日 + * @since v1.0.0 + */ + public Object handle(Object input) { + return input; + } +} diff --git a/src/main/java/com/javaCore/java_thread/threadPool/custom/PThread.java b/src/main/java/com/javaCore/java_thread/threadPool/custom/PThread.java new file mode 100644 index 0000000..19a8d1f --- /dev/null +++ b/src/main/java/com/javaCore/java_thread/threadPool/custom/PThread.java @@ -0,0 +1,66 @@ +package com.javaCore.java_thread.threadPool.custom; + +/** + * @author chenssy + * @date 2016年10月31日 + * @since v1.0.0 + */ +public class PThread extends Thread{ + //线程池 + private ThreadPool pool; + + //任务 + private Runnable target; + + private boolean isShutDown = false; + private boolean isIdle = false; + + public PThread(Runnable target,String name,ThreadPool pool){ + super(name); + this.pool = pool; + this.target = target; + } + + public Runnable getTarget(){ + return target; + } + + public boolean isIdle(){ + return isIdle; + } + + public void run(){ + while(!isShutDown){ + isIdle = true; + if(target != null){ + target.run(); //运行线程 + } + + //任务结束了,到闲置状态 + isIdle = true; + + try { + pool.repool(this); + synchronized (this){ + //线程空闲,等待任务到来 + wait(); + } + } catch (InterruptedException e) { + + } + isIdle = false; + } + } + + public synchronized void setTarget(Runnable newTarget){ + target = newTarget; + //设置任务后,通知run方法,执行任务 + notifyAll(); + } + + //关闭线程 + public synchronized void shutDown(){ + isShutDown = true; + notifyAll(); + } +} diff --git a/src/main/java/com/javaCore/java_thread/threadPool/custom/Test.java b/src/main/java/com/javaCore/java_thread/threadPool/custom/Test.java new file mode 100644 index 0000000..67bfb00 --- /dev/null +++ b/src/main/java/com/javaCore/java_thread/threadPool/custom/Test.java @@ -0,0 +1,42 @@ +package com.javaCore.java_thread.threadPool.custom; + +/** + * @author chenssy + * @date 2016年10月31日 + * @since v1.0.0 + */ +public class Test { + + public static void main(String[] args){ + long begin1 = System.currentTimeMillis(); + for(int i = 0 ; i < 500 ; i++){ + new Thread(new MyThread("no pool_"+i)).start(); + } + long end1 = System.currentTimeMillis(); + + long begin2 = System.currentTimeMillis(); + for(int i = 0 ; i < 500 ; i++){ + ThreadPool.getInstance().start(new MyThread("pool_"+i)); + } + long end2 = System.currentTimeMillis(); + + System.out.println("no pool times:" + (end1 - begin1)); + System.out.println("pool times:" + (end2 - begin2)); + } + + private static class MyThread implements Runnable{ + String name = null; + public MyThread(String name) { + this.name = name; + } + + @Override + public void run() { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/src/main/java/com/javaCore/java_thread/threadPool/custom/ThreadPool.java b/src/main/java/com/javaCore/java_thread/threadPool/custom/ThreadPool.java new file mode 100644 index 0000000..cb824f0 --- /dev/null +++ b/src/main/java/com/javaCore/java_thread/threadPool/custom/ThreadPool.java @@ -0,0 +1,79 @@ +package com.javaCore.java_thread.threadPool.custom; + +import java.util.List; +import java.util.Vector; + +/** + * 自定义线程池 + * @author chenssy + * @date 2016/10/31 21:38 + */ +public class ThreadPool { + private static ThreadPool instance = null; + + //空闲的线程队列 + private List idleThreads; + + private int threadCounter; + private boolean isShutDown = false; + + private ThreadPool(){ + this.idleThreads = new Vector(5); + threadCounter = 0; + } + + public int getCreatedThreadsCount(){ + return threadCounter; + } + + public synchronized static ThreadPool getInstance(){ + if(instance == null){ + instance = new ThreadPool(); + } + return instance; + } + + //将线程加入线程池中 + protected synchronized void repool(PThread thread){ + if(!isShutDown){ + idleThreads.add(thread); + }else{ + thread.shutDown(); + } + } + + /** + * 停止池中所有线程 + * + * @author chenssy + * @date 2016年10月31日 + * @since v1.0.0 + */ + public synchronized void shutDown(){ + isShutDown = true; + for(int i = 0 ; i < idleThreads.size() ; i++){ + PThread thread = (PThread) idleThreads.get(i); + thread.shutDown(); + } + } + + public synchronized void start(Runnable runnable){ + PThread thread = null; + //有空闲线程 直接使用 + if(idleThreads.size()> 0){ + int lastIndex = idleThreads.size() - 1; + thread = (PThread) idleThreads.get(lastIndex); + + idleThreads.remove(thread); + + //执行任务 + thread.setTarget(thread); + }else{ //没有空闲线程,则创建新的线程 + threadCounter++; + thread = new PThread(runnable,"PThread #" + threadCounter,this); + + //启动该线程 + thread.start(); + } + } +} diff --git a/src/main/java/com/javaCore/jvm/_1/JConsole.java b/src/main/java/com/javaCore/jvm/_1/JConsole.java deleted file mode 100644 index 8413cde..0000000 --- a/src/main/java/com/javaCore/jvm/_1/JConsole.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.javaCore.jvm._1; - -import java.util.ArrayList; -import java.util.List; - - -public class JConsole { - static class OOMObject{ - public byte[] placeholder = new byte[64 * 1024]; - } - - public static void fillHeap(int numb) throws InterruptedException { - List list = new ArrayList(); - for(int i = 0 ; i < numb ; i++){ - Thread.sleep(500); - list.add(new OOMObject()); - } - System.gc(); - } - - public static void main(String[] args) throws InterruptedException { - fillHeap(1000); - } -} diff --git a/src/main/java/com/redis/JRedisPoolUtils.java b/src/main/java/com/redis/JRedisPoolUtils.java new file mode 100644 index 0000000..beae345 --- /dev/null +++ b/src/main/java/com/redis/JRedisPoolUtils.java @@ -0,0 +1,73 @@ +package com.redis; + +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; + +/** + * Redis的连接池 + * + * @author:chenming + * @date : 2016/10/31 8:56 + */ +public class JRedisPoolUtils { + private final static String REDIS_IP = "localhost"; + + //可用连接实例的最大数目,默认值为8; + //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。 + private static int MAX_ACTIVE = 1024; + + //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。 + private static int MAX_IDLE = 200; + + //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException; + private static int MAX_WAIT = 10000; + + private static int TIMEOUT = 10000; + + //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的; + private static boolean TEST_ON_BORROW = true; + + private static JedisPool jedisPool = null; + + /** + * 初始化连接池 + */ + static { + JedisPoolConfig config = new JedisPoolConfig(); + config.setMaxActive(MAX_ACTIVE); + config.setMaxIdle(MAX_IDLE); + config.setMaxWait(MAX_WAIT); + config.setTestOnBorrow(TEST_ON_BORROW); + jedisPool = new JedisPool(config,REDIS_IP); + } + + /** + * 获取Redis实例 + * + * @author chenming + * @date 2016-11-06 + * @since v1.0.0 + */ + public synchronized static Jedis getJedis(){ + if(jedisPool != null){ + return jedisPool.getResource(); + }else{ + return null; + } + } + + /** + * 释放jedis资源 + * + * @author chenming + * @date 2016-11-06 + * @since v1.0.0 + */ + public static void returnJedis(final Jedis jedis){ + if(jedisPool != null){ + jedisPool.returnResource(jedis); + } + } + +} diff --git a/src/main/java/com/redis/JRedisTest.java b/src/main/java/com/redis/JRedisTest.java new file mode 100644 index 0000000..6a330e2 --- /dev/null +++ b/src/main/java/com/redis/JRedisTest.java @@ -0,0 +1,157 @@ +package com.redis; + +import org.junit.Before; +import org.junit.Test; +import redis.clients.jedis.Jedis; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @Author: chenssy + * @Date: 2016/10/30 9:41 + */ +public class JRedisTest { + private Jedis jedis = null; + + @Before + public void setUp(){ + //连接redis服务器 + jedis = new Jedis("localhost"); + } + + /** + * String Test + * + * @author chenssy + * @date 2016-10-30 + * @since v1.0.0 + */ + @Test + public void stringTest(){ + jedis.set("name", "chenssy"); + System.out.println(jedis.get("name")); + + jedis.append("name","_cmblogs.com"); + System.out.println(jedis.get("name")); + + jedis.del("name"); + System.out.println(jedis.get("name")); + + jedis.mset("name","chenssy","blog","cmsblogs"); + System.out.println(jedis.get("name") + "--" + jedis.get("blog")); + } + + /** + * Map test + * + * @author chenssy + * @date 2016-10-30 + * @since v1.0.0 + */ + @Test + public void mapTest(){ + Map user = new HashMap(); + user.put("name","chenssy"); + user.put("sex","boy"); //O(∩_∩)O~ + user.put("github","chenssy89"); + user.put("QQ","122448894"); + + jedis.hmset("user" ,user); + + //第一个参数是存入redis中map对象的key,后面跟的是放入map中的对象的key,后面的key可以跟多个,是可变参数 + List list = jedis.hmget("user","name","sex","github","QQ"); + System.out.println(list); + + jedis.hdel("user","QQ"); + System.out.println(jedis.hmget("user", "name", "QQ")); + System.out.println("user 中元素的个数:" + jedis.hlen("user")); + System.out.println("jedis 中是否存在user:" + jedis.exists("user")); + System.out.println("user 中的key:" + jedis.hkeys("user")); + System.out.println("user 中的key:"+jedis.hvals("user")); + } + + /** + * List Test + * + * @author chenssy + * @date 2016年10月30日 + * @since v1.0.0 + */ + @Test + public void listTest(){ + jedis.del("list"); + + jedis.lpush("list","chenssy"); + jedis.lpush("list","boy"); + jedis.lpush("list","chenss89"); + jedis.lpush("list","122448894"); + + /* + *再取出所有数据jedis.lrange是按范围取出, + *第一个是key,第二个是起始位置,第三个是结束位置,jedis.llen获取长度 -1表示取得所有 + */ + + System.out.println(jedis.lrange("list",0,-1)); + System.out.println(jedis.lpop("list")); + System.out.println(jedis.lrange("list",0,-1)); + } + + /** + * Set 集合Test + * + * @author chenssy + * @date 2016年10月30日 + * @since v1.0.0 + */ + @Test + public void setTest(){ + jedis.sadd("set","chenssy"); + jedis.sadd("set","boy"); + jedis.sadd("set","chenssy89"); + jedis.sadd("set","122448894"); + jedis.sadd("set","chenssy"); + + System.out.println(jedis.smembers("set")); + System.out.println(jedis.sismember("set", "boy")); + System.out.println(jedis.srandmember("set")); + System.out.println(jedis.scard("set")); + } + + /** + * 排序 + * + * @author chenssy + * @date 2016年10月30日 + * @since v1.0.0 + */ + @Test + public void sortTest(){ + jedis.del("sort"); + + jedis.rpush("sort","8"); + jedis.rpush("sort","7"); + jedis.rpush("sort","9"); + jedis.rpush("sort","6"); + jedis.rpush("sort","4"); + jedis.rpush("sort","5"); + + System.out.println(jedis.lrange("sort",0,-1)); + System.out.println(jedis.sort("sort")); + System.out.println(jedis.lrange("sort",0,-1)); + } + + /** + * 连接池test + * + * @author chenming + * @date 2016年11月06日 + * @since v1.0.0 + */ + @Test + public void redisPoolTest(){ + JRedisPoolUtils.getJedis().set("pool","chenssy-redis-pool"); + System.out.println(JRedisPoolUtils.getJedis().get("pool")); + } +} diff --git a/src/main/java/com/redis/RedisInvokeTest.java b/src/main/java/com/redis/RedisInvokeTest.java new file mode 100644 index 0000000..d78f83b --- /dev/null +++ b/src/main/java/com/redis/RedisInvokeTest.java @@ -0,0 +1,151 @@ +package com.redis; + +import org.junit.Test; +import redis.clients.jedis.*; + +import java.util.Arrays; +import java.util.List; + +/** + * Redis 调用方式 + * + * @author chenming + * @date 2016年11月6日 16:12 + */ +public class RedisInvokeTest { + + /** + * 普通同步方式 + * + * @author chenming + * @date 2016年11月06日 + * @since v1.0.0 + */ + @Test + public void normalTest() { + Jedis jedis = new Jedis("localhost"); + + long begin = System.currentTimeMillis(); + + for (int i = 0; i < 1000; i++) { + //set之后都可以返回结果,标记是否成功 + System.out.println(i + "---" + jedis.set("n_" + i, "n_" + i)); + } + + long end = System.currentTimeMillis(); + + System.out.println("normal Set:" + (end - begin)); + + jedis.disconnect(); + } + + /** + * 事务方式调用 + * + * 主要目的是保障,一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令 + * + * @author chenming + * @date 2016-11-06 + * @since v1.0.0 + */ + @Test + public void transTest() { + Jedis jedis = new Jedis("localhost"); + + long begin = System.currentTimeMillis(); + Transaction transaction = jedis.multi(); + for (int i = 0; i < 1000; i++) { + transaction.set("t_" + i, "t_" + i); + } + List result = transaction.exec(); + + long end = System.currentTimeMillis(); + + System.out.println("Transaction Set:" + (end - begin)); + jedis.disconnect(); + System.out.println(result); + } + + /** + * 管道方式调用 + * 采用异步方式,一次发送多个指令,不同步等待其返回结果 + * + * @author chenming + * @date 2016-11-06 + * @since v1.0.0 + */ + @Test + public void PipelinedTest() { + Jedis jedis = new Jedis("localhost"); + + long begin = System.currentTimeMillis(); + Pipeline pipeline = jedis.pipelined(); + for (int i = 0; i < 1000; i++) { + pipeline.set("p_" + i, "p_" + i); + } + List result = pipeline.syncAndReturnAll(); + + long end = System.currentTimeMillis(); + + System.out.println("pipeline Set:" + (end - begin)); + jedis.disconnect(); + System.out.println(result); + } + + /** + * 分布式直连同步调用/异步改为ShardedJedisPipeline 即可 + * + * @author chenming + * @date 2016-10-31 + * @since v1.0.0 + */ + @Test + public void shardNormalTest(){ + List shards = Arrays.asList( + new JedisShardInfo("localhost",6379), + new JedisShardInfo("localhost",6380) + ); + + ShardedJedis sharding = new ShardedJedis(shards); + + long start = System.currentTimeMillis(); + for (int i = 0; i < 1000; i++) { + String result = sharding.set("shardNormal " + i, "sn" + i); + } + + long end = System.currentTimeMillis(); + System.out.println("shardNormal SET: " + (end - start)); + + sharding.disconnect(); + } + + /** + * 分布式连接池异步调用 + * + * @author chenming + * @date 2016-10-31 + * @since v1.0.0 + */ + @Test + public void shardPipelinedPoolTest(){ + List shards = Arrays.asList( + new JedisShardInfo("localhost",6379), + new JedisShardInfo("localhost",6380)); + + ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(),shards); + + ShardedJedis one = pool.getResource(); + ShardedJedisPipeline pipeline = one.pipelined(); + + long start = System.currentTimeMillis(); + for (int i = 0; i < 1000; i++) { + pipeline.set("shardPipelinedPool" + i, "n" + i); + } + List results = pipeline.syncAndReturnAll(); + long end = System.currentTimeMillis(); + + pool.returnResource(one); + System.out.println("shardPipelinedPool SET: " + (end - start)); + pool.destroy(); + } +} diff --git a/src/main/java/com/redis/Test.java b/src/main/java/com/redis/Test.java new file mode 100644 index 0000000..2d39fe0 --- /dev/null +++ b/src/main/java/com/redis/Test.java @@ -0,0 +1,4 @@ +package com.redis; + +public class Test { +} diff --git a/src/main/resources/rebel.xml b/src/main/resources/rebel.xml new file mode 100644 index 0000000..49eb40f --- /dev/null +++ b/src/main/resources/rebel.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/test/Test.java b/src/test/Test.java new file mode 100644 index 0000000..cabd6d4 --- /dev/null +++ b/src/test/Test.java @@ -0,0 +1,12 @@ +package test; + +import java.util.concurrent.CopyOnWriteArrayList; + +public class Test { + + public static void main(String[] args) { + CopyOnWriteArrayList c = new CopyOnWriteArrayList(); + c.get(1); + } + +}

AltStyle によって変換されたページ (->オリジナル) /