informasi kontak saya
Surat[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Menjelaskan pengetahuan dasar NIO pada level ava, untuk tinjauan dasar
Di Java, NIO (Non-blocking I/O atau New I/O) adalah kumpulan API operasi input/output baru yang diperkenalkan di Java SE 1.4 dan versi berikutnya.
Dibandingkan dengan model IO tradisional, model ini memberikan efisiensi lebih tinggi dan kemampuan pemrosesan bersamaan yang lebih baik. Fitur utama NIO adalah fitur non-pemblokirannya, yang memungkinkan satu thread mengelola beberapa saluran I/O, sehingga sangat meningkatkan kinerja aplikasi dalam skenario konkurensi tinggi.
Skenario penggunaan Java NIO sangat cocok untuk situasi di mana sejumlah besar koneksi bersamaan perlu diproses. Misalnya, di server jaringan, satu thread dapat mengelola ribuan koneksi klien tanpa perlu mengalokasikan thread independen untuk setiap koneksi . Dapat secara signifikan mengurangi konsumsi sumber daya sistem dan meningkatkan kemampuan pemrosesan
Saluran adalah media aliran data di Java NIO. Bersifat dua arah dan dapat digunakan untuk membaca data atau menulis data. Keuntungan utama saluran adalah non-pemblokiran, artinya satu thread dapat mengelola beberapa saluran. Ketika tidak ada kejadian yang terjadi pada saluran, thread tidak akan diblokir dan malah dapat menangani tugas lainnya. Jenis saluran utama meliputi:
FileChannel
: Digunakan untuk operasi membaca dan menulis file. Dapat digunakan untuk menulis data dari buffer ke file, atau untuk membaca data dari file ke buffer.SocketChannel
: Digunakan untuk koneksi TCP dalam komunikasi jaringan, dan dapat digunakan untuk membaca dan menulis data.ServerSocketChannel
: Digunakan untuk menerima koneksi SocketChannel baru, mirip dengan ServerSocket tradisional.DatagramChannel
: Digunakan untuk komunikasi UDP, yang dapat mengirim dan menerima datagram.Buffer adalah objek yang digunakan untuk menyimpan data di NIO. Ini adalah array byte yang dapat menulis data dan membaca data darinya. Buffer memiliki kapasitas tertentu dan memiliki dua properti penting: posisi dan batas.
Jenis buffer utama adalahByteBuffer
、CharBuffer
、ShortBuffer
、IntBuffer
、LongBuffer
、FloatBuffer
DanDoubleBuffer
, setiap tipe berhubungan dengan tipe data primitif.
Selector adalah multiplexer di NIO yang memungkinkan satu thread memantau peristiwa dari berbagai saluran, seperti membaca, menulis, menghubungkan, dan menerima peristiwa. Pemilih memberi tahu aplikasi ketika salah satu saluran siap untuk operasi I/O. Penggunaan penyeleksi sangat meningkatkan kemampuan pemrosesan konkurensi aplikasi jaringan karena tidak perlu membuat thread untuk setiap koneksi.
Metode utama penyeleksi meliputi:
select()
: Memblokir hingga setidaknya satu saluran siap untuk operasi I/O.selectedKeys()
: Mengembalikan Set yang berisi objek SelectionKey dari semua saluran yang disiapkan.wakeup()
: Interupsi diblokirselect()
transfer.SelectionKey
Ini adalah hubungan antara penyeleksi dan saluran. Ini mewakili status pendaftaran saluran pada pemilih, termasuk saluran, penyeleksi, koleksi acara yang diminati, dan koleksi acara siap pakai.
Ini adalah model I/O paling tradisional. Di Java, Socket dan ServerSocket API tradisional didasarkan pada pemblokiran I/O. Dalam mode ini, ketika thread memulai operasi baca atau tulis, thread diblokir hingga operasi I/O selesai. Jika tidak ada data yang perlu dibaca untuk operasi baca, atau operasi tulis tidak dapat segera diselesaikan, thread akan menunggu hingga operasi selesai.
Fitur:
I/O non-pemblokiran adalah bagian dari kerangka Java NIO (I/O Baru), yang memungkinkan thread memulai operasi baca dan tulis tanpa diblokir. Jika tidak ada data yang perlu dibaca untuk operasi baca, atau operasi tulis tidak dapat segera diselesaikan, thread tidak akan ditangguhkan dan dapat terus melakukan tugas lainnya.
Fitur:
Multiplexing adalah memantau beberapa deskriptor file secara bersamaan melalui satu thread, dan hanya beroperasi pada deskriptor jika sudah siap (biasanya berarti data dapat dibaca, atau buffer tulis dapat ditulis). Selector digunakan di Java untuk mengimplementasikan multiplexing.
Fitur:
Melihat:
Dalam aplikasi praktis, I/O non-blocking sering digunakan bersamaan dengan multiplexing. Misalnya, server dapat menggunakan Selector untuk memantau beberapa SocketChannel. Ketika SocketChannel memiliki data yang dapat dibaca atau ditulis, Selector akan memberi tahu server, dan server akan memproses SocketChannel khusus ini dengan cara yang tidak memblokir.
Di Java, Stream dan Channel adalah dua cara berbeda dalam memproses aliran data. Keduanya masing-masing termasuk dalam perpustakaan IO standar dan perpustakaan NIO. Berikut perbandingan detail kedua konsep tersebut:
Stream adalah bagian dari model IO (blocking IO) standar Java, yang menyediakan cara untuk membaca dan menulis data secara berurutan. Aliran dibagi menjadi dua jenis: InputStream dan OutputStream, yang masing-masing digunakan untuk membaca dan menulis data.Aliran ini dapat berupa aliran byte (sepertiInputStream
, OutputStream
) atau aliran karakter (sepertiReader
, Writer
)。
Fitur:
close()
metode untuk melepaskan sumber daya.Mulai dari Java 7, pernyataan try-with-resources dapat menutup implementasi secara otomatisAutoCloseable
Sumber daya antarmuka, termasuk Stream. Saluran adalah bagian dari model Java NIO (IO Baru), yang memberikan tingkat abstraksi lebih tinggi daripada Stream, sehingga memungkinkan pemrosesan data lebih efisien. Saluran bisa bersifat dua arah, artinya dapat digunakan untuk membaca dan menulis data.Jenis Saluran utama meliputiFileChannel
、SocketChannel
、ServerSocketChannel
DanDatagramChannel
。
Fitur:
Meringkaskan
Di Java, model operasi I/O dapat diklasifikasikan berdasarkan dua dimensi yaitu sinkron/asinkron dan pemblokiran/non-pemblokiran.
definisi : I/O pemblokiran sinkron adalah model I/O paling tradisional. Saat thread memanggil operasi I/O (seperti membaca atau menulis), thread akan diblokir hingga operasi selesai. Ini berarti thread tidak dapat melakukan tugas lain apa pun hingga operasi selesai.
Fitur:
InputStream
、OutputStream
、Socket
DanServerSocket
pemandangan.Contoh:
Gunakan tradisionalInputStream
DanOutputStream
Untuk membaca dan menulis file:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class SyncBlockingIOExample {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("input.txt");
FileOutputStream fos = new FileOutputStream("output.txt")) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
definisi : Dalam I/O non-pemblokiran sinkron, thread tidak akan diblokir setelah memanggil operasi I/O. Jika operasi tidak dapat segera diselesaikan, metode akan segera kembali, biasanya mengembalikan nilai khusus (seperti -1 atau 0) atau mengeluarkan pengecualian untuk menunjukkan bahwa operasi tidak selesai.
Fitur:
Channels
DanBuffers
, dengan menyebutconfigureBlocking(false)
Atur saluran ke mode non-pemblokiran.Contoh:
Menggunakan NIOFileChannel
Untuk membaca dan menulis tanpa pemblokiran:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;
public class SyncNonBlockingIOExample {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("input.txt");
FileOutputStream fos = new FileOutputStream("output.txt");
FileChannel inChannel = fis.getChannel();
FileChannel outChannel = fos.getChannel()) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
inChannel.configureBlocking(false);
while (inChannel.read(buffer) > 0) {
buffer.flip();
outChannel.write(buffer);
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
definisi: Penggunaan model I/O multipleks sinkronSelector
(pemilih) untuk memantau banyakChannel
peristiwa.Saat utas memanggilSelector.select()
, itu akan diblokir hingga setidaknya ada satuChannel
Peristiwa (seperti dapat dibaca, dapat ditulis, permintaan koneksi, dll.) terjadi.
Fitur:
Channel
, meningkatkan konkurensi.Selector
DanSelectionKey
Mekanisme yang secara efisien dapat menangani sejumlah besar koneksi bersamaan.Contoh:
Menggunakan NIOFileChannel
Untuk membaca dan menulis tanpa pemblokiran:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Set;
public class SyncMultiplexingIOExample {
public static void main(String[] args) throws IOException {
try (Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open()) {
serverSocketChannel.socket().bind(new InetSocketAddress(8080));
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
if (selector.select() > 0) {
Set<SelectionKey> keys = selector.selectedKeys();
for (SelectionKey key : keys) {
if (key.isAcceptable()) {
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
SocketChannel clientChannel = ssc.accept();
clientChannel.configureBlocking(false);
clientChannel.register(selector, SelectionKey.OP_READ);
}
}
keys.clear();
}
}
}
}
}
definisi : Dalam model I/O non-pemblokiran asinkron, thread kembali segera setelah memulai operasi I/O tanpa menunggu operasi selesai. Ketika operasi selesai, thread akan diberitahu secara asinkron melalui fungsi panggilan balik atau pemberitahuan acara.
Fitur:
AsynchronousChannel
Antarmuka dan implementasi subkelasnya, sepertiAsynchronousFileChannel
DanAsynchronousSocketChannel
。Contoh:
Menggunakan NIOAsynchronousFileChannel
Lakukan pembacaan dan penulisan file asinkron:
import java.io.IOException;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.ByteBuffer;
import java.util.concurrent.CountDownLatch;
public class AsyncNonBlockingIOExample {
public static void main(String[] args) throws IOException, InterruptedException {
AsynchronousFileChannel inChannel = AsynchronousFileChannel.open(Paths.get("input.txt"), StandardOpenOption.READ);
AsynchronousFileChannel outChannel = AsynchronousFileChannel.open(Paths.get("output.txt"), StandardOpenOption.WRITE);
ByteBuffer buffer = ByteBuffer.allocate(1024);
CountDownLatch latch = new CountDownLatch(1);
inChannel.read(buffer, 0, buffer, 0, (channel, result) -> {
buffer.flip();
outChannel.write(buffer, 0, buffer, 0, null);
latch.countDown();
});
latch.await();
inChannel.close();
outChannel.close();
}
}
Catatan: Model asinkron memerlukan dukungan dari sistem operasi yang mendasarinya (Kernel)
definisi : Secara teori, model ini tidak ada, karena "asinkron" berarti operasi dilakukan di latar belakang dan thread tidak diblokir. Oleh karena itu, pemblokiran I/O asinkron adalah konsep yang kontradiktif dan tidak akan muncul dalam praktik.
Memilih model I/O yang tepat sangat penting untuk kinerja dan pengelolaan sumber daya. Dalam skenario konkurensi tinggi, model I/O non-pemblokiran sinkron atau I/O multipleks sinkron adalah pilihan umum. Dalam skenario yang memerlukan performa dan kecepatan respons ekstrem, model I/O non-pemblokiran asinkron adalah pilihan pertama.
Konsep Nol-Salinan
Teknologi zero-copy berarti selama proses transmisi data dari satu tempat ke tempat lain, data tidak perlu disalin antara ruang pengguna dan ruang kernel, atau setidaknya mengurangi jumlah salinan tersebut, sehingga meningkatkan efisiensi sistem. Dalam operasi I/O tradisional, ketika data dibaca dari jaringan atau disk, data tersebut terlebih dahulu disalin ke buffer di ruang kernel, dan kemudian disalin dari ruang kernel ke buffer di ruang pengguna. Sebaliknya, dalam zero-copy, data dapat diproses langsung di ruang kernel, atau langsung ditransfer dari ruang kernel ke perangkat jaringan, sehingga mengurangi operasi penyalinan CPU, mengurangi overhead sistem, dan meningkatkan efisiensi transmisi data.
Sumber salinan nol
Konsep zero copy pertama kali muncul dalam desain sistem operasi, yang bertujuan untuk mengatasi hambatan kinerja yang disebabkan oleh penyalinan data dalam operasi I/O tradisional. Pada sistem komputer awal, semua operasi I/O memerlukan banyak salinan data di ruang pengguna dan ruang kernel. Hal ini secara bertahap menjadi hambatan kinerja setelah jaringan berkecepatan tinggi dan disk berkapasitas besar menjadi umum.
Poin teknis utama
Implementasi di Jawa:
Java mendukung teknologi zero-copy melalui kerangka NIO (New I/O). NIO diperkenalkanFileChannel
DanSocketChannel
dan kelas lain, yang menyediakan operasi I/O yang lebih efisien. Secara khusus,FileChannel.transferTo()
DanFileChannel.transferFrom()
Metode dapat mentransfer data secara langsung dari saluran file ke saluran soket atau sebaliknya tanpa memuat data ke dalam buffer, sehingga mencapai nol salinan.
Misalnya, Anda perlu mengirim konten file besar ke jaringan. Pendekatan tradisional adalah membaca konten file terlebih dahulu ke dalam buffer dan kemudian menulis konten buffer ke jaringan. Ini melibatkan dua operasi penyalinan: satu dari disk ke buffer dan satu lagi dari buffer ke jaringan.saat menggunakantransferTo()
Saat menggunakan metode ini, data dapat ditransfer langsung dari disk ke jaringan tanpa memerlukan buffer perantara, sehingga mengurangi jumlah salinan dan mencapai nol salinan.
Contoh penggunaan ByteBuffer:
ByteBuffer
dan lainnyaBuffer
kelas (misalnyaCharBuffer
,ShortBuffer
dll.) menyediakan buffer yang dapat diisi atau dikosongkan tanpa secara langsung melibatkan salinan antara ruang pengguna dan ruang kernel.ByteBuffer
Dapat digunakan secara langsung atau tidak langsung dalam teknologi zero-copy:
ByteBuffer.allocateDirect(size)
DibuatByteBuffer
Instance dipetakan langsung ke memori fisik, melewati heap Java.Ketika buffer tersebut dibandingkan denganFileChannel
atauSocketChannel
Ketika digunakan bersama-sama, data dapat ditransfer secara langsung antara memori fisik dan perangkat keras tanpa memerlukan salinan tambahan melalui heap Java. Hal ini memungkinkan zero-copy yang sebenarnya pada beberapa platform.FileChannel
daritransferTo()
DantransferFrom()
: Metode ini memungkinkan data disimpan secara langsungFileChannel
DanSocketChannel
ditransmisikan antaraByteBuffer
sebagai perantara. Artinya data dapat ditransfer langsung dari disk ke jaringan atau sebaliknya tanpa harus disalin antara ruang pengguna dan ruang kernel.ByteBuffer
dariwrap()
metode:wrap()
Metode ini memungkinkan Anda untuk menggabungkan array byte yang ada atau buffer lain ke dalam aByteBuffer
, jadi tidak perlu menyalin data ke buffer baru. Hal ini berguna untuk menghindari penyalinan data yang tidak diperlukan.ByteBuffer
darislice()
metode:slice()
metode membuat tampilan buffer tanpa menyalin data yang mendasarinya.Artinya besarByteBuffer
Bagi menjadi beberapa buffer yang lebih kecil tanpa menyalin data.Gabungkan ByteBuffer dengan FileChannel:
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
public class ZeroCopyExample {
public static void main(String[] args) {
Path path = Path.of("example.txt");
try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ)) {
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
long transferred = fileChannel.transferTo(0, fileChannel.size(), System.out);
System.out.println("Transferred bytes: " + transferred);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Melihat:
Perlu dicatat bahwa pada kenyataannya, tidak ada salinan nol yang lengkap. Salinan nol yang disebutkan di sini hanya untuk aplikasi kita sendiri, yang tidak memiliki salinan tingkat pengguna. Tetapi bahkan di tingkat pengguna, tidak mungkin untuk tidak melakukan operasi penyalinan sama sekali, tetapi untuk mengurangi salinan sebanyak mungkin. Oleh karena itu, kita dapat memahami bahwa istilah zero copy sebenarnya mengacu pada teknologi pengurangan jumlah salinan data. dan itu tidak berarti bahwa tidak ada operasi penyalinan yang sebenarnya.