单核Java 11上的并发IO

单核Java 11上的并发IO,java,multithreading,concurrency,aws-lambda,Java,Multithreading,Concurrency,Aws Lambda,在使用诸如Erlang和其他具有轻量级并发进程的语言之后,我发现很难理解如何将其转换为Java。如果我使用单核机器,有没有办法执行多个并发IO绑定操作(http) 我发现的是以下ExecutorService和CompletableFuture。我的问题是它们基于线程池。默认线程池使用core#-1,在我使用的单核计算机上,它没有并发性。解决方案是只提供一个自定义执行器和更多线程吗?还是有一种更惯用的方式在Java的单核机器上实现IO绑定并发 我在AWS Lambda上运行这段代码,它只有一个内

在使用诸如Erlang和其他具有轻量级并发进程的语言之后,我发现很难理解如何将其转换为Java。如果我使用单核机器,有没有办法执行多个并发IO绑定操作(http)

我发现的是以下
ExecutorService
CompletableFuture
。我的问题是它们基于线程池。默认线程池使用core#-1,在我使用的单核计算机上,它没有并发性。解决方案是只提供一个自定义
执行器
和更多线程吗?还是有一种更惯用的方式在Java的单核机器上实现IO绑定并发


我在AWS Lambda上运行这段代码,它只有一个内核。

线程是Java中的基本(也是唯一)并发机制
ExecutorService
具有创建具有任意数量线程的线程池的方法;另外,
CompletableFuture
s不限于
ForkJoinPool.commonPool
。提供的线程数=内核数只是CPU绑定任务的方便方法。

对于IO绑定的工作,您可以分配更多线程,正如您所提到的,当它们执行IO时,它们被阻塞,因此其他人仍然可以使用CPU

您还可以看看Project Reactor,如果您不想使用此特定的调度程序手动处理线程,它会很方便:

默认线程池使用core#-1,在我使用的单核计算机上,它没有并发性。”-为什么?并发程序可以很好地在单核机器上运行。它与并行无关

当一个Java线程正在等待I/O时,内核的调度程序将把它移动到等待队列,并运行一些需要CPU时间的其他线程。因此,您可以创建一个包含任意多个线程的线程池,调度程序将负责并发性。即使在单核机器上也能正常工作

这里唯一的限制是要创建的线程数。线程的默认堆栈大小在b/w
512K
1M
之间变化。因此,这不能很好地扩展,在某个时候,您将耗尽线程。在我的系统上,我可以创建大约5k个。像Go这样的语言通过在有限数量的内核线程上多路复用多个goroutine来管理这一点。这需要Go运行时进行调度

如果您想缓解这种情况,您应该研究
NIO
。我写了一个快速的程序,你可以用它来找出有多少并发连接可以通过这种方式支持。导入后应按原样运行:

public class ConcurrentBlockingServer {

  private ExecutorService pool = Executors.newCachedThreadPool();

  public static void main(String[] args) {
    ConcurrentBlockingServer bs = new ConcurrentBlockingServer();
    try {
      bs.listen();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  private void listen() throws IOException {
    int connectionId = 0;
    ServerSocket ss = new ServerSocket(8080);
    while (true) {
      Socket s = ss.accept(); // blocking call, never null
      System.out.println("Connection: " + (++connectionId));
      process(s);
    }
  }

  private void process(Socket s) {
    Runnable task =
        () -> {
          try (InputStream is = s.getInputStream();
              OutputStream os = s.getOutputStream()) {
            int data;
            // -1 is EOF, .read() is blocking
            while (-1 != (data = is.read())) {
              os.write(flipCase(data));
              os.flush();
            }
          } catch (IOException e) {
            e.printStackTrace();
          }
        };
    pool.submit(task);
  }

  private int flipCase(int input) {
    if (input >= 65 && input <= 90) {
      return input + 32;
    } else if (input >= 97 && input <= 122) {
      return input - 32;
    } else {
      return input;
    }
  }
}
公共类ConcurrentBlockingServer{
私有ExecutorService池=Executors.newCachedThreadPool();
公共静态void main(字符串[]args){
ConcurrentBlockingServer bs=新的ConcurrentBlockingServer();
试一试{
听;
}捕获(IOE异常){
e、 printStackTrace();
}
}
私有void listen()引发IOException{
int connectionId=0;
ServerSocket ss=新的ServerSocket(8080);
while(true){
套接字s=ss.accept();//阻塞调用,从不为null
System.out.println(“连接:”+(++connectionId));
过程;
}
}
私有无效进程(套接字){
可运行任务=
() -> {
try(InputStream=s.getInputStream();
OutputStream os=s.getOutputStream(){
int数据;
//-1是EOF,.read()是阻塞
而(-1!=(data=is.read()){
写(flipCase(数据));
os.flush();
}
}捕获(IOE异常){
e、 printStackTrace();
}
};
提交(任务);
}
专用int flipCase(int输入){
如果(输入>=65&&input=97&&input
public class RogueClient {

  private static long noClients = 9000;

  public static void main(String[] args) {
    for (int i = 0; i < noClients; i++) {
      try {
        new Socket("localhost", 8080);
        System.out.println("Connection No: " + i);
      } catch (IOException e) {
        System.err.println("Exception: " + e.getMessage() + ", for connection: " + i);
      }
    }
    try {
      Thread.sleep(Integer.MAX_VALUE);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}