单核Java 11上的并发IO
在使用诸如Erlang和其他具有轻量级并发进程的语言之后,我发现很难理解如何将其转换为Java。如果我使用单核机器,有没有办法执行多个并发IO绑定操作(http) 我发现的是以下单核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上运行这段代码,它只有一个内
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/w512K
到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();
}
}
}