Scalable IO in Java 学习笔记

原文地址:http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf
大神之作原文,值得好好拜读。

笔记整理如下:

Classic Service Designs

在这里插入图片描述

Classic ServerSocket Loop

class Server implements Runnable {
	public void run() {
        try {
            ServerSocket ss = new ServerSocket(PORT);
            while (!Thread.interrupted())
                new Thread(new Handler(ss.accept())).start();
            // or, single-threaded, or a thread pool
        } catch (IOException ex) { /* ... */ }
    }
    static class Handler implements Runnable {
        final Socket socket;
        Handler(Socket s) { socket = s; }
        public void run() {
            try {
                byte[] input = new byte[MAX_INPUT];
                socket.getInputStream().read(input);
                byte[] output = process(input);
                socket.getOutputStream().write(output);
            } catch (IOException ex) { /* ... */ }
        }
        private byte[] process(byte[] cmd) { /* ... */ }
    }
}

Reactor Pattern

Reactor responds to IO events by dispatching the appropriate handler
Handlers perform non-blocking actions

Basic Reactor Design

Single threaded version

在这里插入图片描述

java.nio Support

  • Channels
    Connections to files, sockets etc that support non-blocking reads

  • Buffers
    Array-like objects that can be directly read or written by Channels

  • Selectors
    Tell which of a set of Channels have IO events

  • SelectionKeys
    Maintain IO event status and bindings

Example

class Reactor implements Runnable {
	final Selector selector;
	final ServerSocketChannel serverSocket;
	
	// Reactor 1: Setup
	Reactor(int port) throws IOException {
		selector = Selector.open();
		serverSocket = ServerSocketChannel.open();
		serverSocket.socket().bind(new InetSocketAddress(port));
		serverSocket.configureBlocking(false);
		SelectionKey sk = serverSocket.register(selector, SelectionKey.OP_ACCEPT);
		sk.attach(new Acceptor());
	}
	
	// Reactor 2: Dispatch Loop
	public void run() { // normally in a new Thread
        try {
            while (!Thread.interrupted()) {
                selector.select();
                Set<SelectionKey> selected = selector.selectedKeys();
                Iterator<SelectionKey> it = selected.iterator();
                while (it.hasNext()) {
                    dispatch(it.next());
                }
                selected.clear();
            }
        } catch (IOException e) { /* ... */ }
    }
	
	void dispatch(SelectionKey k) {
        Runnable r = (Runnable) k.attachment();
        if(r != null) {
            r.run();
        }
    }
	
	// Reactor 3: Acceptor
	class Acceptor implements Runnable { // inner
        @Override
        public void run() {
            try {
                SocketChannel c = serverSocket.accept();
                if(c != null) {
                    new Handler(selector, c);
                }
            } catch (IOException e) { /* ... */ }
        }
    }
}
final class Handler implements Runnable{

    final SocketChannel socket;
    final SelectionKey sk;
    ByteBuffer input = ByteBuffer.allocate(MAXIN);
    ByteBuffer output = ByteBuffer.allocate(MAXOUT);
    static final int READING = 0, SENDING = 1;
    int state = READING;
    
    // Reactor 4: Handler setup
    Handler(Selector sel, SocketChannel c) throws IOException {
        socket = c;
        c.configureBlocking(false);
		// Optionally try first read now
        sk = socket.register(sel, 0);
        sk.attach(this);
        sk.interestOps(SelectionKey.OP_READ);
        sel.wakeup();
    }

    boolean inputIsComplete() { /* ... */ }

    boolean outputIsComplete() { /* ... */ }

    void process() { /* ... */ }

	// Reactor 5: Request handling
    @Override
    public void run() {
        try {
            if(state == READING) read();
            else if(state == SENDING) send();
        } catch (IOException e) { /* ... */ }
    }

    void read() throws IOException {
        socket.read(input);
        if(inputIsComplete()) {
            process();
            state = SENDING;
			// Normally also do first write now
            sk.interestOps(SelectionKey.OP_WRITE);
        }
    }

    void send() throws IOException {
        socket.write(output);
        if(outputIsComplete()) {
            sk.cancel();
        }
    }
}

Multithreaded Designs

Worker Thread Pools

在这里插入图片描述

Handler with Thread Pool

class Handler implements Runnable {
	// uses util.concurrent thread pool
	static PooledExecutor pool = new PooledExecutor(...);
	static final int PROCESSING = 3;
	// ...
	synchronized void read() { // ...
		socket.read(input);
		if (inputIsComplete()) {
			state = PROCESSING;
			pool.execute(new Processer());
		}
	}
	synchronized void processAndHandOff() {
		process();
		state = SENDING; // or rebind attachment
		sk.interest(SelectionKey.OP_WRITE);
	}
	class Processer implements Runnable {
		public void run() { processAndHandOff(); }
	}
}

Multiple Reactor Threads

Selector[] selectors; // also create threads
int next = 0;
class Acceptor { // ...
	public synchronized void run() { ...
		Socket connection = serverSocket.accept();
		if (connection != null)
			new Handler(selectors[next], connection);
		if (++next == selectors.length) next = 0;
	}
}

Using Multiple Reactors

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值