实现多线程时读写事件互不影响,直接上代码
1.Server端代码
@Slf4j
public class ServerSocket {
private static final Worker[] worker = new Worker[Runtime.getRuntime().availableProcessors()];
static {
for (int i = 0; i < worker.length; i++) {
worker[i] = new Worker("worker" + i);
}
}
public static void main(String[] args) throws IOException {
Thread.currentThread().setName("boss");
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.bind(new InetSocketAddress("localhost", 1221));
ssc.configureBlocking(false); //开启非阻塞模式
Selector selector = Selector.open();
ssc.register(selector, SelectionKey.OP_ACCEPT);
AtomicInteger atomicInteger = new AtomicInteger();
while (true) {
selector.select();
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
if (key.isAcceptable()) {
ServerSocketChannel channel = (ServerSocketChannel) key.channel();
SocketChannel sc = channel.accept();
log.debug("客户端链接:{}", sc);
sc.configureBlocking(false);
worker[atomicInteger.getAndIncrement() % worker.length].register(sc);
System.out.println("=atomicInteger=======================" + atomicInteger.getAndIncrement());
log.debug("before register----------------------------------");
log.debug("after register----------------------------------");
log.debug("");
}
}
}
}
static class Worker implements Runnable {
private Thread thread;
private Selector selector;
private String name;
private volatile boolean isStart = false;
private ConcurrentLinkedQueue<Runnable> queue = new ConcurrentLinkedQueue();
public Worker(String name) {
= name;
}
public void register(SocketChannel sc) throws IOException {
if (!isStart) {
log.debug("注册事件 work-----------------------------");
selector = Selector.open();
thread = new Thread(this);
thread.setName(name);
thread.start();
isStart = true;
}
queue.add(() -> {
try {
sc.register(selector, SelectionKey.OP_READ);
} catch (ClosedChannelException e) {
throw new RuntimeException(e);
}
});
selector.wakeup();
}
@Override
public void run() {
while (true) {
try {
log.debug("select work-----------------------------");
selector.select();
Runnable poll = queue.poll();
if (null != poll) {
poll.run();
}
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
if (key.isReadable()) {
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(16);
try {
int read = sc.read(byteBuffer);
if (read == -1) {
key.cancel();
sc.close();
}
byteBuffer.flip();
log.info("发送的消息:{}", Charset.defaultCharset().decode(byteBuffer));
} catch (Exception e) {
e.printStackTrace();
key.cancel();
sc.close();
}
}
log.debug("=====================");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
2 客户端代码
public class Cilent {
public static void main(String[] args) throws IOException {
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("127.0.0.1",1221));
socketChannel.write(Charset.defaultCharset().encode("1234567890"));
System.in.read();
}
}