技术文章 > java >  java基础 > 正文

java阻塞和非阻塞的使用

小妮浅浅

在调用程序的时候会出现两种情况,一种是阻塞,另一种是非阻塞。当我们需要某种调用产生结果后执行时,会选择阻塞对程序暂时挂起。而非阻塞的操作是把立刻返回,而不是对线程进行阻止。下面就java中阻塞和非阻塞的概念带来讲解,然后就代码的使用上为大家进行说明。

1.概念

阻塞就是指在调用结果返回之前,当前线程会被挂起,一直处于等待消息通知的状态,不能执行其他业务。只有当调用结果返回之后才能进行其他操作。

非阻塞与阻塞的概念相对应,就是指不能立即得到结果之前,该函数不会阻塞当前线程,而是会立即返回。

2.阻塞式IO

一个新的连接,我们就新开一个线程来处理这个连接,之后的操作全部由那个线程来完成。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
 
#define MAXLEN 4096
 
int main(int argc, char** argv)
{
    int    listenfd, sock_fd;
    struct sockaddr_in     servaddr;
    char    buff[MAXLEN];
    int     n;  
 
    if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
        printf("create socket error: %s(errno: %d)/n",strerror(errno),errno);
        exit(0);
    }   
 
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(8001);
 
    if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
        printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
        exit(0);
    }
 
    if( listen(listenfd, 10) == -1){
        printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
        exit(0);
    }
 
    printf("waiting for client to connect\n");
 
    while(1){
        if( (sock_fd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1){
            printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
            continue;
        }
        n = recv(sock_fd, buff, MAXLEN, 0);
        buff[n] = '\0';
        printf("recv msg from client: %s\n", buff);
        close(sock_fd);
        break;
    }
    close(listenfd);
}

3.非阻塞式IO

非阻塞 IO 的核心在于使用一个 Selector 来管理多个通道,可以是 SocketChannel,也可以是 ServerSocketChannel,将各个通道注册到 Selector 上,指定监听的事件。

public class SelectorServer { 
    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();
 
        ServerSocketChannel server = ServerSocketChannel.open();
        server.socket().bind(new InetSocketAddress(8080));
 
        // 将其注册到 Selector 中,监听 OP_ACCEPT 事件
        server.configureBlocking(false);
        server.register(selector, SelectionKey.OP_ACCEPT);
 
        while (true) {
            int readyChannels = selector.select();
            if (readyChannels == 0) {
                continue;
            }
            Set<SelectionKey> readyKeys = selector.selectedKeys();
            // 遍历
            Iterator<SelectionKey> iterator = readyKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
 
                if (key.isAcceptable()) {
                    // 有已经接受的新的到服务端的连接
                    SocketChannel socketChannel = server.accept();
 
                    // 有新的连接并不代表这个通道就有数据,
                    // 这里将这个新的 SocketChannel 注册到 Selector,监听 OP_READ 事件,等待数据
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                } else if (key.isReadable()) {
                    // 有数据可读
                    // 上面一个 if 分支中注册了监听 OP_READ 事件的 SocketChannel
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                    int num = socketChannel.read(readBuffer);
                    if (num > 0) {
                        // 处理进来的数据...
                        System.out.println("收到数据:" + new String(readBuffer.array()).trim());
                        ByteBuffer buffer = ByteBuffer.wrap("返回给客户端的数据...".getBytes());
                        socketChannel.write(buffer);
                    } else if (num == -1) {
                        // -1 代表连接已经关闭
                        socketChannel.close();
                    }
                }
            }
        }
    }
}

以上就是Java阻塞和非阻塞的使用方法,相信大家已经对程序调用时的两种不同执行方法有所了解,根据我们所想要要达到的结果,分别选择阻塞和非阻塞的操作。

免费视频教程
本文原创发布python学习网,转载请注明出处,感谢您的尊重!
相关文章
 Stream函数在java中的使用
 java中Stream创建的方法
 java Stream结合函数方法
 Stream在java里的终止
 java字符串的格式化输出
 java异步的使用
 同步在java中的应用
相关视频章节
 网络爬虫
 云端部署Web应用程序视频
 Web应用框架Flask和文件模板
 Web应用程序开发概述
 继承和多态
作者信息

小妮浅浅

认证0级讲师

最近文章
java编译命令是什么522
java的jdk是什么411
java Wrapper类的使用812
推荐视频
视频教程分类