单线程版本Reactor模式示例
Reactor反应器
public class EchoServerReactor implements Runnable {
Selector selector;
ServerSocketChannel serverSocketChannel;
public static void main(String[] args) {
new Thread(new EchoServerReactor()).start();
}
void EchoServerReactor() throws Exception{
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(NioDemoConfig.SOCKET_SERVER_IP, NioDemoConfig.SOCKET_SERVER_PORT));
serverSocketChannel.configureBlocking(false);
SelectionKey sk = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
sk.attach(new AcceptorHandler());
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
selector.select();
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> it = selectionKeys.iterator();
while (it.hasNext()) {
SelectionKey sk = it.next();
dispatch(sk);
}
selectionKeys.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void dispatch(SelectionKey sk) {
Runnable handler = (Runnable) (sk.attachment());
if (handler != null) {
handler.run();
}
}
class AcceptorHandler implements Runnable{
@Override
public void run() {
try {
SocketChannel channel = serverSocketChannel.accept();
if (channel != null) {
new EchoHandler(selector, channel);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Handler处理器
public class EchoHandler implements Runnable {
final SocketChannel channel;
final SelectionKey sk;
final ByteBuffer buffer = ByteBuffer.allocate(NioDemoConfig.SEND_BUFFER_SIZE);
static final int RECIEVING = 0, SENDING = 1;
int state = RECIEVING;
EchoHandler(Selector selector, SocketChannel c) throws IOException {
channel = c;
channel.configureBlocking(false);
sk = channel.register(selector, RECIEVING);
sk.attach(this);
sk.interestOps(SelectionKey.OP_READ);
selector.wakeup();
}
@Override
public void run() {
try {
if (state == RECIEVING) {
int length = 0;
while ((length = channel.read(buffer)) > 0) {
System.out.println(new String(buffer.array(), 0, length));
}
buffer.flip();
sk.interestOps(SelectionKey.OP_WRITE);
state = SENDING;
} else if (state == SENDING) {
channel.write(buffer);
buffer.clear();
sk.interestOps(SelectionKey.OP_READ);
state = RECIEVING;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
多线程版本Reactor模式示例
反应器
public class MultiThreadEchoServerReactor {
ServerSocketChannel serverSocketChannel;
AtomicInteger next = new AtomicInteger(0);
Selector[] selectors = new Selector[2];
SubReactor[] subReactors = null;
MultiThreadEchoServerReactor() throws IOException {
selectors[0] = Selector.open();
selectors[1] = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
InetSocketAddress address = new InetSocketAddress(NioDemoConfig.SOCKET_SERVER_IP, NioDemoConfig.SOCKET_SERVER_PORT);
serverSocketChannel.socket().bind(address);
serverSocketChannel.configureBlocking(false);
SelectionKey sk = serverSocketChannel.register(selectors[0], SelectionKey.OP_ACCEPT);
sk.attach(new AcceptorHandler());
SubReactor subReactor1 = new SubReactor(selectors[0]);
SubReactor subReactor2 = new SubReactor(selectors[1]);
subReactors = new SubReactor[]{subReactor1, subReactor2};
}
private void startService() {
new Thread(subReactors[0]).start();
new Thread(subReactors[1]).start();
}
class SubReactor implements Runnable {
final Selector selector;
SubReactor(Selector selector) {
this.selector = selector;
}
@Override
public void run() {
while (!Thread.interrupted()) {
try {
while (!Thread.interrupted()) {
selector.select();
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey sk = iterator.next();
dispatch(sk);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void dispatch(SelectionKey sk) {
Runnable handler = (Runnable) sk.attachment();
if (handler != null) {
handler.run();
}
}
}
class AcceptorHandler implements Runnable {
@Override
public void run() {
try {
SocketChannel channel = serverSocketChannel.accept();
if (channel != null) {
new MultiThreadEchoHandler(selectors[next.get()], channel);
}
} catch (IOException e) {
e.printStackTrace();
}
if (next.incrementAndGet() == selectors.length) {
next.set(0);
}
}
}
public static void main(String[] args) throws IOException {
MultiThreadEchoServerReactor server = new MultiThreadEchoServerReactor();
server.startService();
}
}
处理器
public class MultiThreadEchoHandler implements Runnable {
SocketChannel channel = null;
SelectionKey sk = null;
final ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
static final int RECEIVE = 0, SENDING = 1;
int state = RECEIVE;
static ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("MutiThreadEchoHandler-%d").build();
static ExecutorService pool = new ThreadPoolExecutor(4, 4, 0, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10), factory, new ThreadPoolExecutor.DiscardPolicy());
public MultiThreadEchoHandler(Selector selector, SocketChannel channel) {
try {
this.channel = channel;
channel.configureBlocking(false);
this.sk = channel.register(selector, RECEIVE);
sk.attach(this);
sk.interestOps(SelectionKey.OP_READ);
selector.wakeup();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
pool.execute(new AsycnRun());
}
private class AsycnRun implements Runnable {
@Override
public void run() {
MultiThreadEchoHandler.this.asyncRun();
}
}
public synchronized void asyncRun() {
try {
if (state == SENDING) {
channel.write(byteBuffer);
byteBuffer.flip();
sk.interestOps(SelectionKey.OP_READ);
state = RECEIVE;
} else if (state == RECEIVE) {
int length = 0;
while ((length = channel.read(byteBuffer)) > 0) {
System.out.println(new String(byteBuffer.array(), 0, length));
}
byteBuffer.clear();
sk.interestOps(SelectionKey.OP_WRITE);
state = RECEIVE;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}