Java NIO (Non-blocking I/O) এবং Multithreading একসাথে ব্যবহৃত হলে খুব শক্তিশালী এবং দক্ষ I/O অপারেশন সম্পাদন করা সম্ভব। Java NIO নন-ব্লকিং I/O মডেল ব্যবহার করে ডেটা প্রক্রিয়া করে এবং Multithreading এর মাধ্যমে একাধিক কাজ সমান্তরালে (parallel) করা যায়, যার ফলে অ্যাপ্লিকেশনটির পারফরম্যান্স এবং স্কেলেবিলিটি অনেক বৃদ্ধি পায়।
এখানে আমরা দেখব কিভাবে Java NIO এবং Multithreading এর সংমিশ্রণ ব্যবহার করে একাধিক সংযোগ পরিচালনা করা যায়, বিশেষ করে SocketChannel এবং ServerSocketChannel এর মাধ্যমে নেটওয়ার্ক I/O পরিচালনা করা হয়।
NIO এবং Multithreading: কেন গুরুত্বপূর্ণ?
- Non-blocking I/O: Java NIO ব্লকিং I/O এর বিপরীতে নন-ব্লকিং I/O মডেল ব্যবহার করে। এর মানে হলো, এক্সপেনসিভ I/O অপারেশন চলাকালে থ্রেড ব্লক হবে না। এর ফলে, থ্রেড আরও কার্যকরভাবে অন্য কাজগুলো করতে পারে।
- Multithreading: একাধিক থ্রেড ব্যবহার করে একযোগে বিভিন্ন I/O অপারেশন করা যেতে পারে, যেমন একাধিক ক্লায়েন্ট সংযোগ গ্রহণ করা বা একাধিক ডেটা পাঠানো। এটি সিস্টেমের স্কেলেবিলিটি এবং পারফরম্যান্স উন্নত করে।
- Selector: NIO তে
Selectorএকটি গুরুত্বপূর্ণ উপাদান, যা একাধিক I/O চ্যানেলের ওপর নজর রাখে এবং একাধিক নেটওয়ার্ক অপারেশন পরিচালনা করে। যখন কোনো চ্যানেলে ডেটা আসে, তখন তা সিলেক্টর দ্বারা চিহ্নিত হয় এবং সংশ্লিষ্ট থ্রেড বা প্রোগ্রাম তা গ্রহণ করে।
Java NIO এবং Multithreading সংমিশ্রণ উদাহরণ
এখানে আমরা একটি সিম্পল TCP Server এবং TCP Client উদাহরণ দেখব যেখানে Java NIO এবং Multithreading ব্যবহার করে একাধিক ক্লায়েন্ট সংযোগ পরিচালনা করা হবে। ServerSocketChannel ব্যবহার করে সার্ভার ক্লায়েন্টের সংযোগ গ্রহণ করবে এবং প্রতিটি সংযোগের জন্য একটি নতুন থ্রেড তৈরি করা হবে।
১. TCP Server (Multithreaded NIO Server)
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.concurrent.*;
public class MultiThreadedNIOEchoServer {
private static final int PORT = 8080;
private static final ExecutorService threadPool = Executors.newFixedThreadPool(10); // Thread pool for handling multiple clients
public static void main(String[] args) {
try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open()) {
serverSocketChannel.bind(new InetSocketAddress(PORT));
serverSocketChannel.configureBlocking(false);
System.out.println("Server started on port " + PORT);
while (true) {
// Accept client connections in non-blocking mode
SocketChannel socketChannel = serverSocketChannel.accept();
if (socketChannel != null) {
System.out.println("New client connected: " + socketChannel.getRemoteAddress());
// Handle the client connection in a new thread
threadPool.submit(() -> handleClient(socketChannel));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void handleClient(SocketChannel socketChannel) {
try {
ByteBuffer buffer = ByteBuffer.allocate(256);
while (socketChannel.read(buffer) != -1) {
buffer.flip();
while (buffer.hasRemaining()) {
socketChannel.write(buffer);
}
buffer.clear(); // Clear the buffer for the next read
}
socketChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
এখানে:
- ServerSocketChannel ব্যবহার করে সার্ভারটি পোর্ট 8080 এ ক্লায়েন্ট সংযোগ গ্রহণ করছে।
- প্রতিটি ক্লায়েন্টের জন্য একটি নতুন থ্রেড তৈরি করা হচ্ছে, যা
ExecutorServiceএর মাধ্যমে পরিচালিত হচ্ছে।ExecutorServiceএকাধিক থ্রেডের মাধ্যমে ক্লায়েন্ট সংযোগগুলোর সাথে যোগাযোগ পরিচালনা করে। SocketChannelব্যবহার করে প্রতিটি ক্লায়েন্টের সঙ্গে ডেটা পাঠানো এবং গ্রহণ করা হচ্ছে।
২. TCP Client (Client for Testing)
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
public class NIOClient {
private static final String SERVER_ADDRESS = "localhost";
private static final int SERVER_PORT = 8080;
public static void main(String[] args) {
try (SocketChannel socketChannel = SocketChannel.open()) {
socketChannel.connect(new InetSocketAddress(SERVER_ADDRESS, SERVER_PORT));
String message = "Hello, NIO Server!";
ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
// Send message to server
while (buffer.hasRemaining()) {
socketChannel.write(buffer);
}
buffer.clear();
// Receive echo message from server
socketChannel.read(buffer);
buffer.flip();
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
System.out.println();
} catch (IOException e) {
e.printStackTrace();
}
}
}
এখানে:
SocketChannel.open()ব্যবহার করে ক্লায়েন্ট সার্ভারের সাথে সংযোগ স্থাপন করছে।- সার্ভারে পাঠানোর জন্য একটি বার্তা
ByteBufferব্যবহার করে প্রেরণ করা হচ্ছে। - সার্ভার থেকে প্রতিক্রিয়া গ্রহণ করার জন্য
socketChannel.read()ব্যবহার করা হচ্ছে।
৩. নন-ব্লকিং I/O এবং Multithreading:
- Non-blocking Mode: সার্ভারটি
ServerSocketChannel.configureBlocking(false)ব্যবহার করে নন-ব্লকিং মোডে কনফিগার করা হয়েছে, যাতে সার্ভার কোনো সংযোগের জন্য ব্লক না হয় এবং অন্য ক্লায়েন্টদের সাথে যোগাযোগ করতে পারে। - Multithreading: প্রতিটি ক্লায়েন্ট সংযোগের জন্য একটি নতুন থ্রেড তৈরি করা হচ্ছে, যা
ExecutorService.submit()এর মাধ্যমে পরিচালিত হচ্ছে। এইভাবে, একাধিক ক্লায়েন্টের জন্য সার্ভার পৃথক থ্রেডে কাজ করে এবং প্রতিটি ক্লায়েন্টকে একটি নির্দিষ্ট সময়ের মধ্যে প্রক্রিয়া করতে সক্ষম।
Java NIO এবং Multithreading এর সংমিশ্রণ উচ্চ পারফরম্যান্স নেটওয়ার্কিং এবং I/O অপারেশন পরিচালনা করার জন্য একটি শক্তিশালী পদ্ধতি। NIO এর non-blocking I/O এবং Selector ব্যবহার করে আপনি একাধিক সংযোগ পরিচালনা করতে পারেন, এবং Multithreading ব্যবহার করে একাধিক ক্লায়েন্টের জন্য সার্ভার কার্যকরভাবে কাজ করতে পারে। এই পদ্ধতি Java অ্যাপ্লিকেশনগুলির জন্য স্কেলেবিলিটি এবং কার্যকারিতা বাড়াতে সাহায্য করে, বিশেষ করে যেখানে বৃহৎ সংখ্যক ক্লায়েন্টদের সাথে একযোগে কাজ করতে হয়।
Read more