Sharing Seputar Computing

Berbagi dalam duka…semoga negeri Palestine Merdeka, Israel La’natullah Sirna

Server Multi-thread di Java (3)

Ditulis oleh Husni Ilyas di/pada 13 September 2008

Bagian ini menjelaskan pembangunan thread pooled server sederhana dalam Java. Daripada memulai suatu thread baru per koneksi yang masuk, koneksi dibungkus di dalam suatu Runnable dan ditangani oleh suatu thread pool dengan jumlah thread tetap. Runnable dipelihara pada suatu antrian di dalam thread pool tersebut. Ketika suatu thread di dalam thread pool menjadi idle maka akan diambil suatu Runnable dari antrian dan mengeksekusinya.


Thread Pooled Server in Java
Bagian ini menjelaskan pembangunan thread pooled server sederhana dalam Java. Kode awalnya tetap berdasarkan pada multithreaded server yang dibahas sebelumnya. Perbedaan utama terdapat pada perulangan server. Daripada memulai suatu thread baru per koneksi yang masuk, koneksi dibungkus di dalam suatu Runnable dan ditangani oleh suatu thread pool dengan jumlah thread tetap. Runnable dipelihara pada suatu antrian di dalam thread pool tersebut. Ketika suatu thread di dalam thread pool menjadi idle maka akan diambil suatu Runnable dari antrian dan mengeksekusinya.

Di bawah ini adalah bagaimana perulangan server terlihat dalam versi thread pooled (kode lengkap ada bagian akhir tulisan ini):


while(! isStopped()){
Socket clientSocket = null;
try {
clientSocket = this.serverSocket.accept();
} catch (IOException e) {
if(isStopped()) {
System.out.println("Server Stopped.") ;
return;
}
throw new RuntimeException(
"Error accepting client connection", e);
}

this.threadPool.execute(
new WorkerRunnable(clientSocket, "Thread Pooled Server"));
}

Perubahan hanya di dalam loop dari multithreaded server di sini adalah kode:


this.threadPool.execute(
new WorkerRunnable(clientSocket, "Thread Pooled Server"));

Daripada memulai suatu thread baru per koneksi yang masuk, WorkerRunnable dilewatkan ke thread pool untuk dieksekusi ketika suatu thread dalam pool menjadi idle.
Berikut ini adalah kode untuk class WorkerRunnable yang dilewatkan ke konstruktor thread pekerja:


package servers;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.net.Socket;

public class WorkerRunnable implements Runnable{

protected Socket clientSocket = null;
protected String serverText   = null;

public WorkerRunnable(Socket clientSocket, String serverText) {
this.clientSocket = clientSocket;
this.serverText   = serverText;
}

public void run() {
try {
InputStream input  = clientSocket.getInputStream();
OutputStream output = clientSocket.getOutputStream();
long time = System.currentTimeMillis();
output.write(("HTTP/1.1 200 OK\n\nWorkerRunnable: " + this.serverText + " - " + time + "").getBytes());
output.close();
input.close();
System.out.println("Request processed: " + time);
} catch (IOException e) {
//report exception somewhere.
e.printStackTrace();
}
}
}

Kelebihan dari thread pooled server dibandingkan dengan yang multithreaded adalah bahwa kita dapat mengendalikan jumlah maksimum dari thread yang berjalan pada waktu yang sama. Ini keuntungan jelas tentunya.

Pertama, jika request memerlukan banyak CPU time, RAM atau bandwidth jaringan maka dapat memperlambat server jika banyak request diproses pada waktu yang sama. Sebagai contoh, jika konsumsi memory menyebabkan server menggunakan kombinasi swap memory di dalam disk dan RAM (di luar disk), ini akan mengakibatkan penurunan kinerja yang serius. Dengan mengendaikan jumlah maksimal thread, akan meminimumkan resiko kehabisan sumber daya.

Selanjutnya, mengeksekusi banyak request secara konkuren akan memperlambat semua request yang diproses. Sebagai contoh, jika anda memproses 1000 request secara konkuren dan setiap request memerlukan 1 detik, maka semua request akan memerlukan 1000 detik untuk selesai. Jika kita mengantrikan request dan memrosesnya, katakanlah 10 pada satu waktu, maka 10 request pertama akan selesai setelah 10 detik, 10 berikutnya akan selesai setelah 20 detik dan seterusnya. Hanya 10 request terakhir yang akan selesai setelah 1000 detik. Ini memberikan layanan yang lebih baik kepada client.

Di bawah ini kode lengkap dari class ThreadPooledServer:


package servers;

import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPooledServer implements Runnable{

protected int          serverPort   = 8080;
protected ServerSocket serverSocket = null;
protected boolean      isStopped    = false;
protected Thread       runningThread = null;
protected ExecutorService threadPool = Executors.newFixedThreadPool(10);

public ThreadPooledServer(int port){
this.serverPort = port;
}

public void run(){
synchronized(this){
this.runningThread = Thread.currentThread();
}
openServerSocket();
while(! isStopped()){
Socket clientSocket = null;
try {
clientSocket = this.serverSocket.accept();
} catch (IOException e) {
if(isStopped()) {
System.out.println("Server Stopped.") ;
return;
}
throw new RuntimeException("Error accepting client connection", e);
}
this.threadPool.execute(new WorkerRunnable(clientSocket, "Thread Pooled Server"));
}
System.out.println("Server Stopped.") ;
}

private synchronized boolean isStopped() {
return this.isStopped;
}

public synchronized void stop(){
this.isStopped = true;
try {
this.serverSocket.close();
} catch (IOException e) {
throw new RuntimeException("Error closing server", e);
}
}

private void openServerSocket() {
try {
this.serverSocket = new ServerSocket(this.serverPort);
} catch (IOException e) {
throw new RuntimeException("Cannot open port 8080", e);
}
}
}

Dan contoh kode berikut dapat digunakan untuk menjalankannya:


ThreadPooledServer server = new ThreadPooledServer(9000);
new Thread(server).start();

try {
Thread.sleep(20 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Stopping Server");
server.stop();

Seperti sebelumnya, server dapat diakses dengan web browser pada alamat http://localhost:9000

Tinggalkan Balasan

XHTML: Anda dapat gunakan tag ini: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>