這篇文章給大家介紹怎么在java中實(shí)現(xiàn)阻塞和非阻塞,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
創(chuàng)新互聯(lián)公司成都網(wǎng)站建設(shè)按需策劃,是成都網(wǎng)站推廣公司,為成都VR全景提供網(wǎng)站建設(shè)服務(wù),有成熟的網(wǎng)站定制合作流程,提供網(wǎng)站定制設(shè)計(jì)服務(wù):原型圖制作、網(wǎng)站創(chuàng)意設(shè)計(jì)、前端HTML5制作、后臺(tái)程序開(kāi)發(fā)等。成都網(wǎng)站營(yíng)銷推廣熱線:028-86922220
Java是一門面向?qū)ο缶幊陶Z(yǔ)言,可以編寫桌面應(yīng)用程序、Web應(yīng)用程序、分布式系統(tǒng)和嵌入式系統(tǒng)應(yīng)用程序。
1.概念
阻塞就是指在調(diào)用結(jié)果返回之前,當(dāng)前線程會(huì)被掛起,一直處于等待消息通知的狀態(tài),不能執(zhí)行其他業(yè)務(wù)。只有當(dāng)調(diào)用結(jié)果返回之后才能進(jìn)行其他操作。
非阻塞與阻塞的概念相對(duì)應(yīng),就是指不能立即得到結(jié)果之前,該函數(shù)不會(huì)阻塞當(dāng)前線程,而是會(huì)立即返回。
2.阻塞式IO
一個(gè)新的連接,我們就新開(kāi)一個(gè)線程來(lái)處理這個(gè)連接,之后的操作全部由那個(gè)線程來(lái)完成。
#include#include #include #include #include #include #include #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 的核心在于使用一個(gè) Selector 來(lái)管理多個(gè)通道,可以是 SocketChannel,也可以是 ServerSocketChannel,將各個(gè)通道注冊(cè)到 Selector 上,指定監(jiān)聽(tīng)的事件。
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)); // 將其注冊(cè)到 Selector 中,監(jiān)聽(tīng) OP_ACCEPT 事件 server.configureBlocking(false); server.register(selector, SelectionKey.OP_ACCEPT); while (true) { int readyChannels = selector.select(); if (readyChannels == 0) { continue; } SetreadyKeys = selector.selectedKeys(); // 遍歷 Iterator iterator = readyKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); iterator.remove(); if (key.isAcceptable()) { // 有已經(jīng)接受的新的到服務(wù)端的連接 SocketChannel socketChannel = server.accept(); // 有新的連接并不代表這個(gè)通道就有數(shù)據(jù), // 這里將這個(gè)新的 SocketChannel 注冊(cè)到 Selector,監(jiān)聽(tīng) OP_READ 事件,等待數(shù)據(jù) socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_READ); } else if (key.isReadable()) { // 有數(shù)據(jù)可讀 // 上面一個(gè) if 分支中注冊(cè)了監(jiān)聽(tīng) OP_READ 事件的 SocketChannel SocketChannel socketChannel = (SocketChannel) key.channel(); ByteBuffer readBuffer = ByteBuffer.allocate(1024); int num = socketChannel.read(readBuffer); if (num > 0) { // 處理進(jìn)來(lái)的數(shù)據(jù)... System.out.println("收到數(shù)據(jù):" + new String(readBuffer.array()).trim()); ByteBuffer buffer = ByteBuffer.wrap("返回給客戶端的數(shù)據(jù)...".getBytes()); socketChannel.write(buffer); } else if (num == -1) { // -1 代表連接已經(jīng)關(guān)閉 socketChannel.close(); } } } } } }
關(guān)于怎么在java中實(shí)現(xiàn)阻塞和非阻塞就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。