Selector.select () блокирует FOREVER, но Selector.select (timeout) мгновенно возвращает OP_READ - PullRequest
0 голосов
/ 03 мая 2019

Когда я использую select () без таймаута, он просто навсегда зависает от select (). Но если я использую select (long) с таймаутом, он вернется и позволит мне прочитать данные. (печатает «читай!»)

код:

package org.nio;

import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
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.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author admin
 */
public class ServerNode {

    public static void main(String[] args) throws Exception {
        final ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.bind(new InetSocketAddress(11117));
        ssc.configureBlocking(true);

        System.out.println("");

        int cpus = Math.max(Runtime.getRuntime().availableProcessors(), 3);
        System.out.println("cpus: " + cpus);
        ExecutorService ex = Executors.newFixedThreadPool(cpus + 1);

        final Selector readWriteSel = Selector.open();

        ex.submit(() -> {
            try {
                do {
                    SocketChannel sc = ssc.accept();
                    sc.configureBlocking(false);
                    sc.register(readWriteSel, SelectionKey.OP_READ, sc);
                    System.out.println("Connected! " + sc.socket().getInetAddress().getHostAddress());

                } while (true);

            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        ex.submit(() -> {
            try {
                do {
                    int len = readWriteSel.select();
                    if (len > 0) {
                        System.out.println("2");
                        Iterator<SelectionKey> it = readWriteSel.selectedKeys().iterator();
                        while (it.hasNext()) {
                            System.out.println("3");
                            System.out.println("woke!");
                            SelectionKey key = it.next();
                            if (key.isValid() && key.isReadable()) {
                                SocketChannel sc = (SocketChannel) key.channel();
                                sc.read(ByteBuffer.allocate(1024 * 50));
                                System.out.println("read!");
                            }
                            it.remove();
                        }
                    }

                } while (true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        new Thread() {//client
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                    Socket s = new Socket("127.0.0.1", 11117);
                    OutputStream out = s.getOutputStream();
                    out.write(new byte[1024 * 1024]);
                    out.flush();
                    Thread.sleep(10000);
                    out.write(new byte[1024 * 1024]);
                    out.flush();

                    Thread.sleep(1000000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();

        System.out.println("Ready");
    }
}

Строка, которую нужно изменить, чтобы она не зависала:

int len = readWriteSel.select(1000);

Я неправильно понимаю документы или не должен select () возвращаться, как только есть данные для чтения?

Спасибо!

...