本文使用java的NIO简单实现server-client模式,处理异步队列。
缓存队列类
public class Buffer {
private static Queue<Object> queue = new LinkedList<Object>();
private static int INITSIZE = 2;
private Lock mutex;
private Condition condition;
private Buffer(){
mutex = new ReentrantLock();
condition = mutex.newCondition();
}
public static Buffer getIntance(){
return QueueBuffer.instance;
}
static class QueueBuffer{
private static Buffer instance = new Buffer();
}
public void setInitSize(int size){
INITSIZE = size;
}
public void produce(String msg){
mutex.lock();
try {
while(queue.size() >= INITSIZE ){
System.out.println("queue wait to consume");
condition.await();
}
queue.offer(msg);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
condition.signalAll();
mutex.unlock();
}
}
public Object consume(){
mutex.lock();
try {
while (queue.size() == 0) {
System.out.println("queue wait to produce");
condition.await();
}
return queue.poll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} finally {
condition.signalAll();
mutex.unlock();
}
}
public int getQueueSize(){
return queue.size();
}
}
任务类
public class Task implements Runnable{
private static ConcurrentLinkedQueue<SelectionKey> clq = new ConcurrentLinkedQueue<>();
private NIOServer server;
public Task(NIOServer server){
this.server = server;
}
public static void push(SelectionKey key){
clq.add(key);
}
@Override
public void run() {
try {
SelectionKey key = clq.poll();
server.msgHandle(key);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
服务端类
public class NIOServer {
private ServerSocketChannel serverSocketChannel;
int port = 8080;
private Selector selector;
ByteBuffer recBuffer = ByteBuffer.allocate(1024);
ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
Map<SelectionKey, String> clientMsgs = new HashMap<>();
private static int client_no = 0;
ExecutorService serviceExecutor = Executors.newFixedThreadPool(10);
Task task = null;
public NIOServer(int port) throws IOException {
this.port = port;
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(this.port));
serverSocketChannel.configureBlocking(false);
selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("init finish");
task = new Task(this);
}
public void listen() throws IOException {
while (true) {
System.out.println("server scanning");
int event = selector.select();
if (event > 0) {
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
process(key);
}
}
}
}
private void process(SelectionKey selectionKey) {
SocketChannel client = null;
try {
if (selectionKey.isValid() && selectionKey.isAcceptable()) {
client = serverSocketChannel.accept();
++client_no;
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
} else if (selectionKey.isValid() && selectionKey.isReadable()) {
readHandle(selectionKey);
} else if (selectionKey.isValid() && selectionKey.isWritable()) {
if (clientMsgs.containsKey(selectionKey)) {
writeMsgHanle(selectionKey);
}
}
} catch (Exception e) {
selectionKey.cancel();
try {
selectionKey.channel().close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
private void readHandle(SelectionKey selectionKey) throws IOException, InterruptedException {
SocketChannel client;
client = (SocketChannel) selectionKey.channel();
int len = 0;
while ((len = client.read(recBuffer)) > 0) {
recBuffer.flip();
String sb = new String(recBuffer.array(), 0, len);
clientMsgs.put(selectionKey, sb.toString());
System.out.println("Thread:" + Thread.currentThread().getId() + ",NO." + client_no + " client send msg:"
+ sb.toString());
recBuffer.clear();
}
Task.push(selectionKey);
serviceExecutor.execute(task);
}
public void msgHandle(SelectionKey key) throws IOException {
String msg = clientMsgs.get(key);
String serverMsg = null;
if (msg != null && !"".equals(msg)) {
if (msg.contains("add")) {
msg = msg.substring(msg.indexOf("add") + 4);
Buffer.getIntance().produce(msg);
serverMsg = "server:add " + msg + " to queue successfully";
} else if (msg.contains("poll")) {
String consumeMsg = (String) Buffer.getIntance().consume();
serverMsg = "server:remove " + consumeMsg + " from queue successfully";
} else if (msg.contains("size")) {
serverMsg = "server:size is " + Buffer.getIntance().getQueueSize();
} else {
serverMsg = "server:no such command";
}
} else {
serverMsg = "server:blank message";
}
clientMsgs.put(key,serverMsg);
writeMsgHanle(key);
}
private void writeMsgHanle(SelectionKey key) throws IOException {
String msg = clientMsgs.get(key);
SocketChannel client;
sendBuffer.clear();
sendBuffer.put(msg.getBytes());
client = (SocketChannel) key.channel();
sendBuffer.flip();// write in range of text length
while (sendBuffer.hasRemaining()) {
client.write(sendBuffer);
}
key.interestOps(SelectionKey.OP_READ);
}
public static void main(String[] args) throws IOException {
new NIOServer(8080).listen();
}
}
客户端类
public class NIOClient {
private SocketChannel client;
private Selector selector;
private ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
private ByteBuffer receiveBuffer = ByteBuffer.allocate(1024);
public NIOClient(String ip, int port) throws IOException{
client = SocketChannel.open();
selector = Selector.open();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
client.connect(new InetSocketAddress(ip, port));
while (!client.finishConnect()) {
System.out.println("finish connect");
}
}
public void run(){
while(true){
try {
while (!writeHandle()) {
System.out.println("please input a not empty command");
}
int event = selector.select();
if (event > 0) {
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if (key.isValid() && key.isReadable()) {
readHandle(key);
}
iterator.remove();
}
}
} catch (Exception e) {
e.printStackTrace();
if (client.isOpen()) {
try {
client.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
}
private void readHandle(SelectionKey key) throws IOException {
SocketChannel scChannel = null;
scChannel = (SocketChannel) key.channel();
receiveBuffer.clear();
int len = 0;
if ((len = scChannel.read(receiveBuffer)) > 0) {
receiveBuffer.flip();
String msg = new String(receiveBuffer.array(),0,len);
System.out.println(msg);
}
}
public boolean writeHandle() throws IOException{
Scanner scanner = new Scanner(System.in);
String line = scanner.nextLine();
if (line != null && line.length() > 0) {
sendBuffer.clear();
sendBuffer.put(line.getBytes());
sendBuffer.flip();
while (sendBuffer.hasRemaining()) {
client.write(sendBuffer);
}
return true;
}else{
return false;
}
}
public static void main(String[] args) throws IOException {
new NIOClient("127.0.0.1", 8080).run();
}
}