package com.wan.reactor;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
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.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class MultiThreadEchoServerReactor {
ServerSocketChannel serverSocket;
AtomicInteger next = new AtomicInteger(0);
Selector bossSelector = null;
Selector[] workSelectors = new Selector[2];
Reactor[] workReactors = null;
Reactor bossReactor = null;
MultiThreadEchoServerReactor() throws IOException {
bossSelector = Selector.open();
workSelectors[0] = Selector.open();
workSelectors[1] = Selector.open();
serverSocket = ServerSocketChannel.open();
InetSocketAddress address =
new InetSocketAddress(
8080);
serverSocket.socket().bind(address);
serverSocket.configureBlocking(false);
SelectionKey sk = serverSocket.register(
bossSelector, SelectionKey.OP_ACCEPT);
sk.attach(new AcceptorHandler());
bossReactor = new Reactor(bossSelector);
Reactor workReactor1 = new Reactor(workSelectors[0]);
Reactor workReactor2 = new Reactor(workSelectors[1]);
workReactors = new Reactor[]{workReactor1, workReactor2};
}
private void startService() {
new Thread(bossReactor).start();
new Thread(workReactors[0]).start();
new Thread(workReactors[1]).start();
}
public static void main(String[] args) throws IOException {
new MultiThreadEchoServerReactor().startService();
}
class Reactor implements Runnable {
final Selector selector;
public Reactor(Selector selector) {
this.selector = selector;
}
public void run() {
try {
while (!Thread.interrupted()) {
selector.select(1000);
Set<SelectionKey> selectedKeys =
selector.selectedKeys();
if (null == selectedKeys || selectedKeys.size() == 0) {
continue;
}
Iterator<SelectionKey> it = selectedKeys.iterator();
while (it.hasNext()) {
SelectionKey sk = it.next();
dispatch(sk);
}
selectedKeys.clear();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
void dispatch(SelectionKey sk) {
Runnable handler = (Runnable) sk.attachment();
if (handler != null) {
handler.run();
}
}
}
class AcceptorHandler implements Runnable {
public void run() {
try {
SocketChannel channel = serverSocket.accept();
System.out.println("接收到一个新的连接");
if (channel != null) {
int index = next.get();
System.out.println("选择器的编号:" + index);
Selector selector = workSelectors[index];
new MultiThreadEchoHandler(selector, channel);
}
} catch (IOException e) {
e.printStackTrace();
}
if (next.incrementAndGet() == workSelectors.length) {
next.set(0);
}
}
}
class MultiThreadEchoHandler implements Runnable {
final SocketChannel channel;
final SelectionKey sk;
final ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
static final int RECIEVING = 0, SENDING = 1;
int state = RECIEVING;
ExecutorService pool = Executors.newFixedThreadPool(4);
MultiThreadEchoHandler(Selector selector, SocketChannel c) throws
IOException {
channel = c;
channel.configureBlocking(false);
channel.setOption(StandardSocketOptions.TCP_NODELAY, true);
sk = channel.register(selector, 0);
sk.attach(this);
sk.interestOps(SelectionKey.OP_READ);
selector.wakeup();
System.out.println("新的连接 注册完成");
}
public void run() {
pool.execute(new AsyncTask());
}
public synchronized void asyncRun() {
try {
if (state == SENDING) {
channel.write(byteBuffer);
byteBuffer.clear();
sk.interestOps(SelectionKey.OP_READ);
state = RECIEVING;
} else if (state == RECIEVING) {
int length = 0;
while ((length = channel.read(byteBuffer)) > 0) {
System.out.println(new String(byteBuffer.array(), 0, length));
}
byteBuffer.flip();
sk.interestOps(SelectionKey.OP_WRITE);
state = SENDING;
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
class AsyncTask implements Runnable {
public void run() {
MultiThreadEchoHandler.this.asyncRun();
}
}
}
}