Java 全局共享整数
我正在学习Java 全局共享整数,java,netty,Java,Netty,我正在学习Netty并尝试实现一个简单的计数器,其中所有客户机共享一个整数,他们输入一个数字,整数值按该数字递增 这是我的密码: Server.java package nettyincvalue; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.Even
Netty
并尝试实现一个简单的计数器,其中所有客户机共享一个整数
,他们输入一个数字,整数
值按该数字递增
这是我的密码:
Server.java
package nettyincvalue;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server {
private int port;
private Integer value;
public Server(int port) {
this.port = port;
this.value = 0;
}
public void run(){
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap server = new ServerBootstrap();
server.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ServerInit(this.value))
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = server.bind(port).sync();
f.channel().closeFuture().sync();
} catch (InterruptedException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) {
new Server(12345).run();
}
}
package nettyincvalue;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
public class ServerInit extends ChannelInitializer<SocketChannel> {
private Integer value;
public ServerInit(Integer value) {
this.value = value;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new StringDecoder());
pipeline.addLast(new ServerHandler(this.value));
}
}
package nettyincvalue;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class ServerHandler extends ChannelInboundHandlerAdapter {
private Integer value;
public ServerHandler(Integer value) {
this.value = value;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
String s = (String) msg;
try {
Integer i = Integer.parseInt(s.substring(0, s.length() - 1));
this.value += i;
System.out.println("Value its now: " + this.value);
} catch (NumberFormatException n) {
System.out.println("Not a number received");
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.err.println(cause.getMessage());
ctx.close();
}
}
ServerInit.java
package nettyincvalue;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server {
private int port;
private Integer value;
public Server(int port) {
this.port = port;
this.value = 0;
}
public void run(){
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap server = new ServerBootstrap();
server.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ServerInit(this.value))
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = server.bind(port).sync();
f.channel().closeFuture().sync();
} catch (InterruptedException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) {
new Server(12345).run();
}
}
package nettyincvalue;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
public class ServerInit extends ChannelInitializer<SocketChannel> {
private Integer value;
public ServerInit(Integer value) {
this.value = value;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new StringDecoder());
pipeline.addLast(new ServerHandler(this.value));
}
}
package nettyincvalue;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class ServerHandler extends ChannelInboundHandlerAdapter {
private Integer value;
public ServerHandler(Integer value) {
this.value = value;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
String s = (String) msg;
try {
Integer i = Integer.parseInt(s.substring(0, s.length() - 1));
this.value += i;
System.out.println("Value its now: " + this.value);
} catch (NumberFormatException n) {
System.out.println("Not a number received");
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.err.println(cause.getMessage());
ctx.close();
}
}
单独来说,它是工作的,当一个客户机通过nc输入一个它递增但不是全局递增的数字时,我的意思是当一个不同的客户机启动时,计数器设置为0。您的变量没有正确的同步;它通常应该声明为volatile,以确保所有线程都看到更新的值,并且您需要同步使用它的块。但是,在您的情况下,使用原子整数将更简单、更有效。您的变量没有正确的同步;它通常应该声明为volatile,以确保所有线程都看到更新的值,并且您需要同步使用它的块。但是,在您的情况下,使用原子整数将更简单、更有效。您的变量没有正确的同步;它通常应该声明为volatile,以确保所有线程都看到更新的值,并且您需要同步使用它的块。但是,在您的情况下,使用原子整数将更简单、更有效。您的变量没有正确的同步;它通常应该声明为volatile,以确保所有线程都看到更新的值,并且您需要同步使用它的块。但是,在您的情况下,使用原子整数将更简单、更有效。谢谢!我不知道原子整数。但由于这是一个学术练习,我解决了这个问题,在我自己的类中封装了一个int,它可以工作,我只在使用int或Integer时遇到这个问题。简单地问一下,这个解决方案会出现concurreny问题还是需要同步增量方法?是的,Java整数是不可变的对象,共享它没有意义。@JoséRicardoRibeiro经典的读取(threadA)-读取(threadB)-更新(threadA)-更新仍然会有问题(threadB,但丢失threadA的更新)场景。这正是AtomicInteger#addAndGet()的内容避免。请注意,
AtomicInteger
是自Java 5以来核心Java库的一部分,因此请确保您不能继续使用它。谢谢!我不知道AtomicInteger。但由于这是一个学术练习,我在自己的类中封装了一个int解决了这个问题,并且它可以工作,我只在使用int或Inte时才会遇到这个问题问一个简单的问题,这个解决方案会出现concurreny问题还是需要同步增量方法?对,Java整数是不可变的对象,共享它没有意义。@JoséRicardoRibeiro经典的read(threadA)-read(threadB)-update(threadA)-update仍然会有问题(threadB,但丢失threadA的更新)场景。这正是AtomicInteger#addAndGet()的内容避免。请注意,AtomicInteger
是自Java 5以来核心Java库的一部分,因此请确保您不能继续使用它。谢谢!我不知道AtomicInteger。但由于这是一个学术练习,我在自己的类中封装了一个int解决了这个问题,并且它可以工作,我只在使用int或Inte时才会遇到这个问题问一个简单的问题,这个解决方案会出现concurreny问题还是需要同步增量方法?对,Java整数是不可变的对象,共享它没有意义。@JoséRicardoRibeiro经典的read(threadA)-read(threadB)-update(threadA)-update仍然会有问题(threadB,但丢失threadA的更新)场景。这正是AtomicInteger#addAndGet()的内容避免。请注意,AtomicInteger
是自Java 5以来核心Java库的一部分,因此请确保您不能继续使用它。谢谢!我不知道AtomicInteger。但由于这是一个学术练习,我在自己的类中封装了一个int解决了这个问题,并且它可以工作,我只在使用int或Inte时才会遇到这个问题问一个简单的问题,这个解决方案会出现concurreny问题还是需要同步增量方法?对,Java整数是不可变的对象,共享它没有意义。@JoséRicardoRibeiro经典的read(threadA)-read(threadB)-update(threadA)-update仍然会有问题(threadB,但丢失threadA的更新)场景。这正是AtomicInteger#addAndGet()
避免的。需要注意的是,AtomicInteger
是自Java 5以来核心Java库的一部分,因此请确保您不能继续使用它。