欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:JavaIO、NIO和序列化

柚子快報邀請碼778899分享:JavaIO、NIO和序列化

http://yzkb.51969.com/

JavaIO與NIO

阻塞IO模型非阻塞IO模型多路復(fù)用IO模型事件輪詢機制的偽源碼

信號驅(qū)動IO模型異步IO模型JAVA IO包JAVA NIONIO的緩沖區(qū)NIO的非阻塞完全寫入ChannelBufferSelector實現(xiàn)多連接的客戶端代碼示例

JAVA序列化(創(chuàng)建客服用的Java對象)保持(持久化)對象及其狀態(tài)到內(nèi)存或者磁盤序列化對象以字節(jié)數(shù)組保存(靜態(tài)成員不保存)序列化用戶遠程和對象傳輸序列化IDTransient關(guān)鍵字阻止該變量被序列化到文件中

阻塞IO模型

最傳統(tǒng)的一種IO 模型,即在讀寫數(shù)據(jù)過程中會發(fā)生阻塞現(xiàn)象。當(dāng)用戶線程發(fā)出IO請求之后,內(nèi)核會去查看數(shù)據(jù)是否就緒,,如果沒有就緒就會等待數(shù)據(jù)就緒,而用戶線程就會處于阻塞狀態(tài),用戶線程交出CPU。當(dāng)數(shù)據(jù)就緒之后,內(nèi)核會將數(shù)據(jù)拷貝到用戶線程,并返回結(jié)果給用戶線程,用戶線程才會接觸block狀態(tài)。 典型的阻塞IO模型的例子為:

data=socket.read();

如果數(shù)據(jù)沒有就緒,就會一直阻塞在read方法

非阻塞IO模型

又叫BIO,當(dāng)用戶線程發(fā)起一個read操作后,并不需要等待,而是馬上就得到了一個結(jié)果。如果結(jié)果是一個error,他就知道數(shù)據(jù)還沒有準(zhǔn)備好,于是它在此發(fā)送read操作。一旦內(nèi)核中的數(shù)據(jù)準(zhǔn)備好了,并且再次收到了用戶線程的請求,那么它馬上就將數(shù)據(jù)拷貝到了用戶線程,然后返回。所以事實上,在非阻塞IO模型中,用戶線程需要不斷地詢問內(nèi)核數(shù)據(jù)是否就緒,也就是說非阻塞IO不會交出CPU,而會一直占用CPU。 典型的非阻塞IO模型一般如下:

while(true){

data=socket.read();

if(data!=error){

//在這里處理數(shù)據(jù)

break;

}

}

但是對于非阻塞IO就有一個非常嚴(yán)重的問題,在while循環(huán)中需要不斷地去詢問內(nèi)核數(shù)據(jù)是否就緒,這樣會導(dǎo)致CPU占用率非常高,因此一般情況下很少使用while循環(huán)這種方式來讀取數(shù)據(jù)。

多路復(fù)用IO模型

多路復(fù)用IO模型是目前使用的比較多的模型。JavaNIO實際上就是多路復(fù)用IO。在多路復(fù)用IO模型中,會有一個線程不斷去輪詢多個socket狀態(tài),只有當(dāng)socket真正有讀寫事件時,才真正調(diào)用實際的IO讀寫操作。因為在多路復(fù)用IO模型中,只需要使用一個線程就可以管理多個socket,系統(tǒng)不需要建立新的進程或線程,也不必維護這些進程和線程,并且只有在真正有socket讀寫時間在進行時,才會使用IO資源,所以它大大減少了資源占用。在JavaNIO中,是通過selector.select()去查詢每個通道是否有到達事件,如果沒有事件,則一直阻塞在那里,因此這種方式會導(dǎo)致用戶線程的阻塞。多路復(fù)用IO模式,通過一個線程就可以管理多個socket,只有當(dāng)socket真正有讀寫事件發(fā)生才會占用資源來進行實際的讀寫操作。因此多路復(fù)用IO比較適用連接數(shù)比較多的情況。 另外多路復(fù)用IO比非阻塞IO效率高的原因是因為在非阻塞IO中,不斷地詢問socket狀態(tài)時是通過用戶線程去進行的,而在多路復(fù)用IO中,輪詢每個socket是在內(nèi)核中進行的,這個效率要比用戶線程高得多。 不過要注意的是,多路復(fù)用IO模型師通過輪詢的方式來檢測是否有事件到達,并且對到達的事件注意進行響應(yīng),因此對于多路復(fù)用IO模型來說,一旦事件響應(yīng)體很大,那么就會導(dǎo)致后續(xù)的事件遲遲得不到處理,并且會影響新的事件輪詢

事件輪詢機制的偽源碼

下面是Java NIO事件輪詢機制的偽源碼,幫助理解NIO的工作原理:

import java.nio.channels.Selector;

import java.nio.channels.SelectionKey;

import java.util.Set;

public class NIOEventLoop {

private Selector selector;

public void run() {

while (true) {

// 等待事件

int readyChannels = selector.select();

if (readyChannels == 0) {

continue;

}

// 處理事件

Set selectedKeys = selector.selectedKeys();

for (SelectionKey key : selectedKeys) {

if (key.isValid() && key.isReadable()) {

// 處理讀事件

} else if (key.isValid() && key.isWritable()) {

// 處理寫事件

}

}

selectedKeys.clear();

}

}

}

在這個示例中,我們首先創(chuàng)建一個選擇器 Selector 對象。然后,在 run() 方法中,我們不斷循環(huán)等待事件:調(diào)用 select() 方法等待事件的發(fā)生,如果沒有事件發(fā)生則繼續(xù)等待。如果有事件發(fā)生,我們就處理它們:獲取所發(fā)生事件的 SelectionKey 集合,并根據(jù) isReadable() 和 isWritable() 方法判斷事件類型。最后,我們清空已處理的 SelectionKey 集合,然后繼續(xù)等待事件的發(fā)生。

這個示例演示了Java NIO的事件輪詢機制的基本原理:使用選擇器 Selector 對象等待事件的發(fā)生,并處理所發(fā)生的事件。在實際應(yīng)用中,我們通常會使用多個線程來處理不同類型的事件,以提高性能和響應(yīng)速度。

信號驅(qū)動IO模型

在信號驅(qū)動IO模型中,當(dāng)用戶線程發(fā)起一個IO請求事件,會給對應(yīng)的socket注冊一個信號函數(shù),然后用戶線程會繼續(xù)執(zhí)行,當(dāng)內(nèi)核數(shù)據(jù)就緒時就會發(fā)送一個信號給用戶線程,用戶線程接收到信號之后,便在型號函數(shù)中調(diào)用IO讀寫操作來進行實際的IO請求操作。

在Java中,可以利用NIO框架來實現(xiàn)信號驅(qū)動IO。下面是一個簡單的基于Java NIO實現(xiàn)的例子:

import java.nio.channels.Pipe;

import java.nio.channels.SelectionKey;

import java.nio.channels.Selector;

import java.nio.channels.spi.SelectorProvider;

public class SignalDrivenIOExample {

public static void main(String[] args) throws Exception {

// 創(chuàng)建管道

Pipe pipe = Pipe.open();

// 創(chuàng)建選擇器

Selector selector = SelectorProvider.provider().openSelector();

// 注冊管道讀事件到選擇器中

pipe.source().configureBlocking(false);

pipe.source().register(selector, SelectionKey.OP_READ);

// 啟動信號

Signal.handle(new Signal("IO"), new SignalHandler() {

@Override

public void handle(Signal signal) {

// 處理IO事件

try {

selector.selectNow();

} catch (IOException e) {

e.printStackTrace();

}

}

});

// 無限循環(huán)等待信號驅(qū)動IO事件

while (true) {

try {

Thread.sleep(Long.MAX_VALUE);

} catch (InterruptedException e) {

break;

}

}

}

}

此示例使用Java NIO框架創(chuàng)建了一個管道,將管道的讀事件注冊到選擇器中。然后,我們使用Signal類啟動一個名為 “IO” 的信號,并為其注冊一個信號處理程序Handler。當(dāng)接收到 “IO” 信號時,處理程序會調(diào)用選擇器的 selectNow() 方法來檢查是否有管道讀事件發(fā)生。最后,我們通過一個無限循環(huán)等待信號驅(qū)動IO事件的發(fā)生。這樣,我們就成功地使用信號驅(qū)動IO實現(xiàn)了一個簡單的輸入監(jiān)聽程序。

異步IO模型

異步IO模型是最理想的IO模型,在異步IO模型中,當(dāng)用戶線程發(fā)起read操作之后,立刻就可以開始去做其他的事。而另一方面,從內(nèi)核的角度,當(dāng)它受到一個asynchronous read之后,它會立刻返回,說明read請求已經(jīng)成功發(fā)起了,因此不會對用戶線程產(chǎn)生任何的block。然后,內(nèi)核會等待數(shù)據(jù)準(zhǔn)備完成,然后將數(shù)據(jù)拷貝到用戶線程,當(dāng)這一切都完成之后,內(nèi)核會給用戶線程發(fā)送一個信號,告訴它read操作完成了。也就是說用戶線程完全不需要實際的整個IO操作是如何進行的,只需要先發(fā)起一個請求,當(dāng)接收到內(nèi)核返回的成功信號時表示IO操作已經(jīng)完成,可以直接使用數(shù)據(jù)。 也就是說在異步IO模型中,IO操作的兩個階段都不會阻塞用戶線程,這兩個階段都是由內(nèi)核自動完成,然后發(fā)送一個信號告知用戶線程已經(jīng)操作完成。用戶線程中不需要再次調(diào)用IO函數(shù)進行具體的讀寫。這點適合信號驅(qū)動模型有所不同的,在信號驅(qū)動模型中,當(dāng)用戶線程接收到信號表示數(shù)據(jù)已經(jīng)就緒,然后需要用戶線程調(diào)用IO函數(shù)進行時機的讀寫操作;而在異步IO模型中,收到信號表示IO操作已經(jīng)完成,不需要再在用戶線程中調(diào)用IO函數(shù)進行實際的讀寫操作。 注意: 異步IO是需要操作系統(tǒng)的底層支持的,在java7中提供Asynchronous IO

Java NIO提供了異步IO模型的支持,它通過使用非阻塞IO和事件輪詢機制來實現(xiàn)異步IO。

下面是一個基于Java NIO實現(xiàn)的異步IO模型的偽代碼:

import java.nio.*;

import java.nio.channels.*;

public class AsynchronousIO {

private ByteBuffer readBuffer = ByteBuffer.allocate(1024);

private ByteBuffer writeBuffer = ByteBuffer.allocate(1024);

public void read(SelectableChannel channel) {

channel.read(readBuffer, this, new CompletionHandler() {

public void completed(Integer bytesRead, AsynchronousIO aio) {

if (bytesRead == -1) {

// 讀取結(jié)束

return;

}

// 處理讀取到的數(shù)據(jù)

readBuffer.flip();

byte[] bytes = new byte[readBuffer.remaining()];

readBuffer.get(bytes);

System.out.print(new String(bytes));

readBuffer.clear();

// 繼續(xù)讀取

channel.read(readBuffer, aio, this);

}

public void failed(Throwable exc, AsynchronousIO aio) {

// 處理讀取失敗

}

});

}

public void write(SelectableChannel channel, byte[] data) {

writeBuffer.put(data);

writeBuffer.flip();

channel.write(writeBuffer, this, new CompletionHandler() {

public void completed(Integer bytesWritten, AsynchronousIO aio) {

// 處理寫入成功

writeBuffer.compact();

if (writeBuffer.hasRemaining()) {

// 如果還有數(shù)據(jù),繼續(xù)寫

channel.write(writeBuffer, aio, this);

}

}

public void failed(Throwable exc, AsynchronousIO aio) {

// 處理寫入失敗

}

});

}

}

在這個示例中,我們使用 SelectableChannel 對象來讀取和寫入數(shù)據(jù)。read() 方法通過調(diào)用 channel.read() 來實現(xiàn)異步讀取,當(dāng)事件完成時,CompletionHandler 中的 completed() 將會被回調(diào),我們在其中處理讀取到的數(shù)據(jù)并繼續(xù)讀取。

同樣的,write() 方法通過調(diào)用 channel.write() 來實現(xiàn)異步寫入,當(dāng)事件完成時,CompletionHandler 中的 completed() 將會被回調(diào),我們在其中處理寫入成功并繼續(xù)寫入。

在實際應(yīng)用中,我們通常會使用多個線程來處理不同類型的異步IO事件,以提高性能和響應(yīng)速度。

JAVA IO包

Java IO包包括以下類和接口:

1. InputStream 和 OutputStream:用于讀取和寫入字節(jié)流的類和接口 2. Reader 和 Writer:用于讀取和寫入字符流的類和接口。 3. File:用于操作文件和目錄的類。 4. RandomAccessFile:用于隨機訪問文件的類。 5. FileDescriptor:使用底層文件描述符進行文件訪問的類。 6. FileInputStream 和 FileOutputStream:用于讀取和寫入文件的字節(jié)流的類。 7. FileReader 和 FileWriter:用于讀取和寫入文件的字符流的類。 8. BufferedInputStream 和 BufferedOutputStream:用于處理緩沖區(qū)的字節(jié)流類。 9. BufferedReader 和 BufferedWriter:用于處理緩沖區(qū)的字符流類。 10. DataInputStream 和 DataOutputStream:用于讀取和寫入基本數(shù)據(jù)類型的字節(jié)流類。 11. InputStreamReader 和 OutputStreamWriter:將字節(jié)流轉(zhuǎn)換為字符流的類。 12. ObjectInputStream 和 ObjectOutputStream:用于讀取和寫入 Java 對象的類。 13. PipedInputStream 和 PipedOutputStream:用于在不同線程之間進行通信的字節(jié)流類。 14. PushbackInputStream:允許將字節(jié)推回輸入流的類。 15. SequenceInputStream:允許將多個輸入流合并為一個流的類。

這些類和接口提供了豐富的功能,使得 Java IO 包成為 Java 編程中不可或缺的一部分。

JAVA NIO

NIO主要有三大核心部分:Channel(通道)、Buffer(緩沖區(qū))、Selector(選擇區(qū))。 傳統(tǒng)IO基于字節(jié)流和字符流進行操作,而NIO基于Channel和Buffer(緩沖區(qū))進行操作,數(shù)據(jù)總是從通道讀取到緩沖區(qū)中,或者從緩沖區(qū)寫入到通道中。Selector(選擇區(qū))用于監(jiān)聽多個通道的事件(比如:連接打開,數(shù)據(jù)到達) 因此,單個線程可以監(jiān)聽多個數(shù)據(jù)通道。 NIO和傳統(tǒng)IO之間第一個最大的區(qū)別就是,IO是面向流的,NIO是面向緩沖區(qū)的。

NIO的緩沖區(qū)

JavaIO面向流意味著每次從流中讀取一個或多個字節(jié),直到讀取所有字節(jié),他們沒有被緩存在任何地方。此外,他不能前后移動流中的數(shù)據(jù)。如果需要前后移動從流中讀取的數(shù)據(jù),需要先將它緩存到一個緩沖區(qū)。 NIO的緩沖導(dǎo)向方法不同。數(shù)據(jù)讀取到一個它稍后處理的緩沖區(qū),需要時可在緩沖區(qū)中前后移動。這就增加了處理過程中的靈活性。但是,還需要檢查是否該緩沖區(qū)中包含所有你需要除磷的數(shù)據(jù)。而且,需確保當(dāng)更多的數(shù)據(jù)讀入緩沖區(qū)時,不需要覆蓋緩沖區(qū)中尚未處理的數(shù)據(jù)。

NIO的非阻塞

IO的各種流是阻塞的。這意味著,當(dāng)一個線程調(diào)用read()或write()時,該線程被阻塞,直到有一些數(shù)據(jù)被讀取,或數(shù)據(jù)完全寫入。該線程在此期間不能再干任何事情了。

NIO的非阻塞模式,使一個線程從某通道發(fā)送請求讀取數(shù)據(jù),但是它僅能得到目前可用的數(shù)據(jù),如果目前沒有數(shù)據(jù)可用時,就什么都不會獲取,而不是保持線程阻塞。所以直至數(shù)據(jù)變得可以讀取之前,該線程繼續(xù)做其他的事情。

非阻塞寫也是如此,一個線程請求寫入一些數(shù)據(jù)到某通道,但不需要等待它完全寫入,這個線程同時可以去做別的事情?,F(xiàn)成通常將非阻塞IO的空閑時間用于在其他通道上執(zhí)行IO操作,索引一個單獨的線程現(xiàn)在可以管理多個輸入和輸出通道

完全寫入

**完全寫入指的是將線程請求寫入的數(shù)據(jù)全部寫入到通道中,直到通道緩沖區(qū)已經(jīng)被填滿,或者所有數(shù)據(jù)都已經(jīng)被寫入到通道中。**在非阻塞寫中,即使緩沖區(qū)已經(jīng)被填滿,或者只是寫入了一部分數(shù)據(jù),寫入操作也會持續(xù)進行,同時將剩余的待寫入數(shù)據(jù)返回給調(diào)用方,以便該調(diào)用方可以進行其他操作。這與阻塞寫相比,阻塞寫將等待所有數(shù)據(jù)完全寫入后才會返回。因此,非阻塞寫可以提高程序的效率,避免了線程阻塞和資源浪費。

Channel

**Channel,國內(nèi)大多翻譯成通道。Channel和IO中的Stream(流)是差不多一個等級的。**只不過Stream是單向的,譬如:InputStream和OutputStream,而Channel是雙向的,既可以用來進行讀操作,也可以用來進行寫操作。 NIO中的Channel的主要實現(xiàn)有:

FileChannelDatagramChannelSocketChannelServerSockertChannel

不難看出,以上分別對應(yīng)文件IO、UDP、TCP(Server和Client)

Buffer

Buffer(緩沖區(qū)),實際上就是一個容器,是一個連接數(shù)組。Channel提供從文件、網(wǎng)絡(luò)讀取數(shù)據(jù)的渠道,但是讀取或?qū)懭氲臄?shù)據(jù)都必須經(jīng)過Buffer。 客戶端發(fā)送數(shù)據(jù)時,必須先將數(shù)據(jù)存入Buffer中,然后將Buffer中的內(nèi)容寫入通道。服務(wù)端這邊接受數(shù)據(jù)必須通過Channel將數(shù)據(jù)讀入到Buffer中,然后再從Buffer中取出數(shù)據(jù)來處理。 在NIO中,Buffer是一個頂層父類,他是一個抽象類,常用的Buffer有ByteBuffer、IntBuffer、CharBuffer、LongBuffer、DoubleBuffer、FloatBuffer、ShortBuffer

Selector

Selector是NIO的核心類,Selector能夠檢測多個注冊的通道上是否有事件發(fā)生,如果有事件發(fā)生,便獲取事件然后針對每個事件進行相應(yīng)的響應(yīng)處理。這樣一來,只是用一個單線程就可以管理多個通道,也就是管理多個連接。這樣使得只有在連接真正的有讀寫事件發(fā)生時,才會調(diào)用函數(shù)來進行讀寫,就大大減少了系統(tǒng)開銷,并且不必為每個連接都創(chuàng)建一個線程,不用去維護多個線程,并且避免了多線程之間的上下文切換導(dǎo)致的開銷。

實現(xiàn)多連接的客戶端代碼示例

這里提供一個基于Java NIO實現(xiàn)多連接的客戶端代碼示例:

import java.io.IOException;

import java.net.InetSocketAddress;

import java.nio.ByteBuffer;

import java.nio.channels.SelectionKey;

import java.nio.channels.Selector;

import java.nio.channels.SocketChannel;

import java.util.Iterator;

import java.util.Scanner;

import java.util.Set;

public class MultiNIOClient {

// 客戶端自動生成的id

private static final String CLIENT_ID = "client" + System.currentTimeMillis();

public static void main(String[] args) throws IOException {

// 創(chuàng)建Selector選擇器

Selector selector = Selector.open();

// 創(chuàng)建多個SocketChannel連接遠程服務(wù)器

SocketChannel socketChannel1 = SocketChannel.open();

SocketChannel socketChannel2 = SocketChannel.open();

socketChannel1.connect(new InetSocketAddress("localhost", 8888));

socketChannel2.connect(new InetSocketAddress("localhost", 8888));

socketChannel1.configureBlocking(false);

socketChannel2.configureBlocking(false);

// 注冊到選擇器中

socketChannel1.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE, CLIENT_ID + "-001");

socketChannel2.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE, CLIENT_ID + "-002");

// 開始循環(huán)處理請求

while (true) {

// 選擇已經(jīng)準(zhǔn)備就緒的通道

int readyChannels = selector.select();

if (readyChannels > 0) {

// 遍歷已經(jīng)準(zhǔn)備就緒的通道,處理請求

Set selectedKeys = selector.selectedKeys();

Iterator iterator = selectedKeys.iterator();

while (iterator.hasNext()) {

SelectionKey selectionKey = iterator.next();

if (selectionKey.isReadable()) {

// 讀取數(shù)據(jù)

SocketChannel channel = (SocketChannel) selectionKey.channel();

ByteBuffer buffer = ByteBuffer.allocate(1024);

int bytesRead = channel.read(buffer);

if (bytesRead > 0) {

buffer.flip();

byte[] bytes = new byte[buffer.remaining()];

buffer.get(bytes);

String message = new String(bytes, "UTF-8");

System.out.println("Message received from " + selectionKey.attachment() + ": " + message);

} else if (bytesRead < 0) {

System.out.println(selectionKey.attachment() + " disconnected.");

channel.close();

}

} else if (selectionKey.isWritable()) {

// 發(fā)送數(shù)據(jù)

SocketChannel channel = (SocketChannel) selectionKey.channel();

Scanner scanner = new Scanner(System.in);

System.out.println("Enter message: ");

String message = scanner.nextLine();

if (message.trim().length() > 0) {

ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());

channel.write(buffer);

System.out.println("Message sent from " + selectionKey.attachment() + ": " + message);

}

}

iterator.remove();

}

}

}

}

}

在該示例中,創(chuàng)建了兩個連接并注冊到選擇器中進行監(jiān)聽,分別使用字符串id作為SelectionKey的attachment屬性。通過控制臺輸入消息并往對應(yīng)的SocketChannel發(fā)送消息,同時可以接收來自其他客戶端的消息。

簡單的客戶端到服務(wù)器端的數(shù)據(jù)傳輸示例

客戶端代碼:

import java.io.IOException;

import java.net.InetSocketAddress;

import java.nio.ByteBuffer;

import java.nio.channels.SocketChannel;

public class NIOClient {

public static void main(String[] args) throws IOException {

// 創(chuàng)建SocketChannel通道并連接服務(wù)器

SocketChannel socketChannel = SocketChannel.open();

socketChannel.connect(new InetSocketAddress("localhost", 8888));

// 發(fā)送數(shù)據(jù)

String message = "Hello, Server!";

ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());

socketChannel.write(buffer);

System.out.println("Message sent to the server: " + message);

// 接收數(shù)據(jù)

buffer.clear();

socketChannel.read(buffer);

buffer.flip();

String response = new String(buffer.array(), 0, buffer.limit());

System.out.println("Message received from the server: " + response);

// 關(guān)閉通道

socketChannel.close();

}

}

服務(wù)器端代碼:

import java.io.IOException;

import java.net.InetSocketAddress;

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.Set;

public class NIOServer {

public static void main(String[] args) throws IOException {

// 創(chuàng)建Selector選擇器

Selector selector = Selector.open();

// 創(chuàng)建ServerSocketChannel通道并綁定端口

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

serverSocketChannel.socket().bind(new InetSocketAddress("localhost", 8888));

serverSocketChannel.configureBlocking(false);

serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

// 開始循環(huán)處理請求

while (true) {

// 選擇已經(jīng)準(zhǔn)備就緒的通道

int readyChannels = selector.select();

// 遍歷已經(jīng)準(zhǔn)備就緒的通道,處理請求

if (readyChannels > 0) {

Set selectedKeys = selector.selectedKeys();

Iterator iterator = selectedKeys.iterator();

while (iterator.hasNext()) {

SelectionKey selectionKey = iterator.next();

if (selectionKey.isAcceptable()) {

// 如果是接收請求事件

ServerSocketChannel serverChannel = (ServerSocketChannel) selectionKey.channel();

SocketChannel socketChannel = serverChannel.accept();

// 將通道設(shè)置為非阻塞模式,并注冊到選擇器中

socketChannel.configureBlocking(false);

socketChannel.register(selector, SelectionKey.OP_READ);

System.out.println("Connection Accepted: " + socketChannel.getLocalAddress() + "\n");

} else if (selectionKey.isReadable()) {

// 如果是讀取數(shù)據(jù)事件

SocketChannel socketChannel = (SocketChannel) selectionKey.channel();

ByteBuffer buffer = ByteBuffer.allocate(1024);

int bytesRead = socketChannel.read(buffer);

if (bytesRead > 0) {

buffer.flip();

byte[] bytes = new byte[buffer.remaining()];

buffer.get(bytes);

String message = new String(bytes, "UTF-8");

System.out.println("Message received from client: " + message);

// 將響應(yīng)數(shù)據(jù)返回給客戶端

ByteBuffer responseBuffer = ByteBuffer.wrap(("Server Response: " + message).getBytes());

socketChannel.write(responseBuffer);

} else if (bytesRead < 0) {

// 客戶端關(guān)閉了連接

socketChannel.close();

}

}

iterator.remove();

}

}

}

}

}

在客戶端向服務(wù)端發(fā)送數(shù)據(jù)后,服務(wù)端會接收到數(shù)據(jù)并返回響應(yīng),客戶端再接收到響應(yīng)數(shù)據(jù)。

JAVA序列化(創(chuàng)建客服用的Java對象)

保持(持久化)對象及其狀態(tài)到內(nèi)存或者磁盤

Java平臺允許我們在內(nèi)存中創(chuàng)建可復(fù)用的Java對象,但一般情況下,只有當(dāng)JVM處于運行時,這些對象才可能存在,也就是說這些對象的生命周期不會比JVM的聲明周期更長。但在現(xiàn)實應(yīng)用中,就可能要求在JVM停止運行之后能夠保存 (持久化)指定的對象,并在將來重新讀取被保存的對象。Java對象序列化就能幫助我們實現(xiàn)該功能。

序列化對象以字節(jié)數(shù)組保存(靜態(tài)成員不保存)

使用java對象序列化,在保存對象時,會把其狀態(tài)保存為一組字節(jié),在未來,再將這些字節(jié)組裝成對象。必須注意的是,對象序列化保存的是對象的“狀態(tài)”,即他的成員變量。由此可知,對象序列化不會關(guān)注類中的靜態(tài)變量

序列化用戶遠程和對象傳輸

除了在持久化對象時會用到對象序列化之外,當(dāng)使用RMI(遠程方法調(diào)用),或在網(wǎng)絡(luò)中傳遞對象時,都會用到對象序列化。java序列化API為處理對象序列化提供了一個標(biāo)準(zhǔn)機制,該API簡單易用。

Serializable實現(xiàn)序列化

在java中,只要一個類實現(xiàn)了java.io.Serizliable接口,那么他就可以被序列化。

ObjectOutputStream和ObjectInputStream對對象進行序列化及反序列化writeObject和readObject自定義序列化策略 在類中增加writeObject和readObject方法自定義序列化策略

序列化ID

虛擬機是否允許反序列化,不僅取決于類路徑和功能代碼是否一致,一個非常重要的一點是兩個類序列化ID是否一致(就是private static final long serialVersionUID) 序列化并不保存靜態(tài)變量 序列化字父類說明 要想將父類對象也序列化,就需要讓父類也實現(xiàn)Serializable接口

Transient關(guān)鍵字阻止該變量被序列化到文件中

在變量聲明前加上Transient關(guān)鍵字,可以阻止該變量被序列化到文件中,在被反序列化后,transient變量的值被設(shè)為初始值,如int型的是0,對象型的是null。服務(wù)器端給客戶端發(fā)送序列化對象數(shù)據(jù),對象中有一些數(shù)據(jù)是敏感的,比如密碼字符串等,希望對該密碼字段在序列化時,進行加密,而客戶端如果擁有解密的密鑰,只有在客戶端進行反序列時,才可以對密碼進行讀取,這樣可以一定程度保證序列化對象的數(shù)據(jù)安全。

柚子快報邀請碼778899分享:JavaIO、NIO和序列化

http://yzkb.51969.com/

推薦閱讀

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://m.gantiao.com.cn/post/19593589.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄