Dalam dunia pemrograman, efisiensi dan kecepatan adalah dua aspek yang sering kali diutamakan, terutama ketika berhadapan dengan operasi I/O yang memakan waktu, seperti membaca file. Java, dengan dukungan kuatnya terhadap multithreading, menawarkan cara yang efisien untuk menangani tugas-tugas ini secara paralel. Pada artikel kali ini, kita akan membahas bagaimana Anda bisa menggunakan multithreading untuk membaca dua file teks secara simultan dan kemudian mensinkronisasi konten mereka. Tutorial ini cocok bagi Anda yang ingin meningkatkan kinerja aplikasi yang berinteraksi dengan sistem file.
Dalam postingan kali ini, kita akan langsung bermain dengan User Interface. Karena Multithreading tiada berarti jika kita tidak sekalian bermain dengan User Interface. Mengapa? Karena dengan menerapkan User Interface ke dalam project multithread kita, Secara otomatis kita akan melihat langsung bagaimana multithread itu bekerja. Tidak hanya struktural seperti saat menggunakan interface terminal yang mana satu instruksi tidak akan dapat dieksekusi sebelum instruksi sebelumnya dieksekusi. Itulah alasannya mengapa kita akan langsung menggunakan User Interface pada project kita kali ini.
KELUARAN
Keluaran dari project kita kali ini adalah seperti tangkapan layar di bawah ini.
FLOW PROGRAM
Karena pada project kali ini kita akan menerapkan multithread dan User interface, maka diperlakukan skenario Flow Program yang akan kita terapkan.
Dalam aplikasi yang kita kembangkan, pengguna dapat menambahkan dan memproses dua file teks menggunakan antarmuka yang intuitif. Proses ini digambarkan dalam UML Sequence Diagram yang kita bahas di bawah ini, yang menggambarkan interaksi antara pengguna dan sistem selama eksekusi aplikasi.
Langkah-langkah Utama dan Aplikasi
- Memulai Aplikasi: Pengguna memulai aplikasi yang memperlihatkan sebuah
Main Frame
dengan dua tombol utama: “Tambahkan File” dan “Proses”. - Menambahkan File:
- Pengguna mengklik tombol “Tambahkan File”, yang memicu
Main Frame
untuk membukaFile Selector
. File Selector
adalah JFileChooser yang memungkinkan pengguna memilih dua file teks dari sistem file lokal.- Setelah file dipilih, path dari kedua file tersebut dikembalikan ke
Main Frame
dan ditampilkan dalam bentuk teks, menunjukkan file yang telah terpilih.
- Pengguna mengklik tombol “Tambahkan File”, yang memicu
- Memproses File:
- Dengan file sudah ditambahkan, pengguna kemudian dapat mengklik tombol “Proses”.
Main Frame
memulaiFile Reader
yang bertugas membaca isi dari kedua file yang dipilih.- Selama proses berlangsung,
Progress Bar
di-update secara real time untuk memberikan umpan balik visual kepada pengguna mengenai kemajuan proses. Progress Bar
menampilkan status proses pembacaan dan sinkronisasi, yang memberikan pengalaman interaktif kepada pengguna.
- Menyimpan File Hasil:
- Setelah proses pembacaan dan sinkronisasi selesai,
File Reader
memicuFile Saver
untuk menyimpan hasil. File Saver
menampilkan JFileChooser yang memungkinkan pengguna untuk memilih lokasi dan nama file untuk menyimpan hasil output.- Pengguna memilih lokasi dan nama file, dan hasil proses disimpan ke lokasi yang dipilih.
- Setelah proses pembacaan dan sinkronisasi selesai,
- Penutupan Aplikasi:
- Setelah file berhasil disimpan, aplikasi dapat ditutup atau digunakan untuk sesi lebih lanjut jika diinginkan.
Diagram yang disajikan pada Gambar 2 membantu dalam memahami alur kerja aplikasi secara keseluruhan dan interaksi antar komponen. Ini termasuk bagaimana komponen-komponen seperti Main Frame
, File Selector
, File Reader
, Progress Bar
, dan File Saver
berinteraksi satu sama lain selama siklus hidup aplikasi.
MULAI MEMPROGRAM
1. Membuat Class FileReaderThread.java
Kelas ini bertanggung jawab untuk membaca isi dari file teks yang diberikan. Mari kita ulas metodologi yang digunakan:
- Constructor: Menerima path file sebagai parameter. Ini menyimpan path ke variabel lokal yang akan digunakan untuk membaca file.
- run(): Metode ini di-override dari kelas
Thread
. Di dalamnya, kita membuka file menggunakanBufferedReader
, membaca setiap baris sampai akhir file, dan menyimpannya ke dalamStringBuilder
. Ini memastikan bahwa operasi I/O dilakukan di thread terpisah, sehingga tidak mengganggu responsivitas GUI. - getFileContent(): Setelah file selesai dibaca, metode ini digunakan untuk mendapatkan isi file sebagai string.
Berikut adalah kodenya
import java.io.*;
class FileReaderThread extends Thread {
private String filePath;
private StringBuilder fileContent = new StringBuilder();
public FileReaderThread(String filePath) {
this.filePath = filePath;
}
public void run() {
try {
BufferedReader reader = new BufferedReader(new FileReader(filePath));
String line;
while ((line = reader.readLine()) != null) {
fileContent.append(line).append("\n");
// Tambahkan sleep untuk memperlambat proses
Thread.sleep(100); // Tunda 100 ms untuk setiap baris
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println("Thread was interrupted.");
}
}
public String getFileContent() {
return fileContent.toString();
}
}
2. Membuat Class FileSyncApp.java
Kelas ini adalah jantung dari aplikasi GUI kita. Berikut adalah penjelasan untuk setiap komponen dan metode:
- Konstruktor
FileSyncApp
: Di sini, kita mengatur tampilan utama aplikasi, termasuk membuat buttons, labels, progress bar, dan text area. Layout diatur menggunakanFlowLayout
, yang sederhana dan cukup untuk kebutuhan kita. - ActionListener untuk
addButton
: Ketika tombol “Tambahkan File” diklik,JFileChooser
akan dibuka, memungkinkan pengguna untuk memilih dua file. Setelah file dipilih, nama file ditampilkan di label dan path disimpan untuk proses lebih lanjut. - ActionListener untuk
processButton
: Ini memulai proses pembacaan file. Tombol ini mengaktifkan progress bar dan memulai thread baru yang menjalankan metodeprocessFiles
. - processFiles(String path1, String path2): Metode ini menangani logika untuk memulai thread pembacaan file. Setelah kedua thread selesai, ia meng-update text area dengan isi file dan menghentikan progress bar.
- saveToFile(String content): Setelah file selesai diproses, metode ini memungkinkan pengguna untuk menyimpan konten ke file baru melalui
JFileChooser
.
Penjelasan GUI Components:
- JButton: Dua tombol untuk interaksi pengguna – satu untuk menambahkan file dan satu lagi untuk memulai proses sinkronisasi.
- JLabel: Dua label untuk menampilkan nama file yang dipilih.
- JProgressBar: Sebuah bar untuk memberikan feedback visual tentang proses yang sedang berlangsung.
- JTextArea: Area teks di mana konten file yang diproses ditampilkan.
Berikut adalah Kodenya.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class FileSyncApp extends JFrame {
private JButton addButton;
private JButton processButton;
private JLabel fileLabel1;
private JLabel fileLabel2;
private JProgressBar progressBar;
private JLabel statusLabel;
private String filePath1;
private String filePath2;
private JTextArea textArea;
public FileSyncApp() {
super("File Synchronization Application");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 400);
setLocationRelativeTo(null);
setLayout(new FlowLayout());
addButton = new JButton("Tambahkan File");
processButton = new JButton("Proses");
fileLabel1 = new JLabel("Teks 1: ");
fileLabel2 = new JLabel("Teks 2: ");
progressBar = new JProgressBar(0, 100);
progressBar.setPreferredSize(new Dimension(350, 25));
statusLabel = new JLabel("Status: Idle");
textArea = new JTextArea(10, 35);
textArea.setEditable(false);
add(addButton);
add(processButton);
add(fileLabel1);
add(fileLabel2);
add(progressBar);
add(statusLabel);
add(new JScrollPane(textArea));
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setMultiSelectionEnabled(true);
int option = fileChooser.showOpenDialog(FileSyncApp.this);
if (option == JFileChooser.APPROVE_OPTION) {
File[] files = fileChooser.getSelectedFiles();
if (files.length == 2) {
filePath1 = files[0].getAbsolutePath();
filePath2 = files[1].getAbsolutePath();
fileLabel1.setText("Teks 1: " + files[0].getName());
fileLabel2.setText("Teks 2: " + files[1].getName());
}
}
}
});
processButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
progressBar.setIndeterminate(true);
statusLabel.setText("Processing...");
Thread thread = new Thread(new Runnable() {
public void run() {
processFiles(filePath1, filePath2);
}
});
thread.start();
}
});
}
private void processFiles(String path1, String path2) {
FileReaderThread reader1 = new FileReaderThread(path1);
FileReaderThread reader2 = new FileReaderThread(path2);
reader1.start();
reader2.start();
try {
reader1.join();
reader2.join();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.setText(reader1.getFileContent() + "\n" + reader2.getFileContent());
progressBar.setIndeterminate(false);
statusLabel.setText("Done Processing.");
saveToFile(textArea.getText());
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void saveToFile(String content) {
JFileChooser fileChooser = new JFileChooser();
if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
writer.write(content);
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3. Method Main
Metode ini adalah titik masuk program, yang hanya mengatur agar instance FileSyncApp
ditampilkan. Tambahkan metode ini di class FileSyncApp
.
Berikut adalah metodenya.
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new FileSyncApp().setVisible(true);
}
});
}
Sehingga kode lengkap dari adalah FileSyncApp
sebagai berikut.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class FileSyncApp extends JFrame {
private JButton addButton;
private JButton processButton;
private JLabel fileLabel1;
private JLabel fileLabel2;
private JProgressBar progressBar;
private JLabel statusLabel;
private String filePath1;
private String filePath2;
private JTextArea textArea;
public FileSyncApp() {
super("File Synchronization Application");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 400);
setLocationRelativeTo(null);
setLayout(new FlowLayout());
addButton = new JButton("Tambahkan File");
processButton = new JButton("Proses");
fileLabel1 = new JLabel("Teks 1: ");
fileLabel2 = new JLabel("Teks 2: ");
progressBar = new JProgressBar(0, 100);
progressBar.setPreferredSize(new Dimension(350, 25));
statusLabel = new JLabel("Status: Idle");
textArea = new JTextArea(10, 35);
textArea.setEditable(false);
add(addButton);
add(processButton);
add(fileLabel1);
add(fileLabel2);
add(progressBar);
add(statusLabel);
add(new JScrollPane(textArea));
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setMultiSelectionEnabled(true);
int option = fileChooser.showOpenDialog(FileSyncApp.this);
if (option == JFileChooser.APPROVE_OPTION) {
File[] files = fileChooser.getSelectedFiles();
if (files.length == 2) {
filePath1 = files[0].getAbsolutePath();
filePath2 = files[1].getAbsolutePath();
fileLabel1.setText("Teks 1: " + files[0].getName());
fileLabel2.setText("Teks 2: " + files[1].getName());
}
}
}
});
processButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
progressBar.setIndeterminate(true);
statusLabel.setText("Processing...");
Thread thread = new Thread(new Runnable() {
public void run() {
processFiles(filePath1, filePath2);
}
});
thread.start();
}
});
}
private void processFiles(String path1, String path2) {
FileReaderThread reader1 = new FileReaderThread(path1);
FileReaderThread reader2 = new FileReaderThread(path2);
reader1.start();
reader2.start();
try {
reader1.join();
reader2.join();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.setText(reader1.getFileContent() + "\n" + reader2.getFileContent());
progressBar.setIndeterminate(false);
statusLabel.setText("Done Processing.");
saveToFile(textArea.getText());
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void saveToFile(String content) {
JFileChooser fileChooser = new JFileChooser();
if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
writer.write(content);
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new FileSyncApp().setVisible(true);
}
});
}
}
MENGOMPILASI PROGRAM
Langkah selanjutnya adalah mengkompilasi program sehingga program Java yang sudah kita buat dapat dijalankan. Untuk melakukannya, buka terminal pada komputer Anda dan navigasikan ke tempat Anda menyimpan kedua file Java yang telah dibuat. Setelah Anda berada di lokasi tempat Anda menyimpan kedua file java, Anda dapat mengetikkan perintah berikut ini.
javac FileSyncApp.java
Seperti tangkapan layar di bawah ini
Setelah Anda mengeksekusi perintah di atas, maka Anda akan melihat bahwa class yang diperoleh lebih banyak daripada file java yang sudah kita buat.
Kita tidak perlu mengkompilasi keseluruhan file Java yang sudah kita buat. Kita hanya perlu memgompilasi file Java yang memiliki metode main. Maka secara otomatis seluruh File Java yang berkaitan juga akan ikut terkompilasi.
MENJALANKAN PROGRAM
Setelah kita berhasil mengompilasi File Java yang sudah kita buat, saatnya kita menjalankannya. Untuk menjalankannya kita hanya perlu mengetikkan berikut ini di area terminal yang sama.
java FileSyncApp
Jika tidak terjadi error, maka secara otomatis perintah ini akan menjalankan program FileSyncApp yang sudah kita buat.
Lalu, di manakah letak multithreadnya? Coba kita buka system monitor / task manager yang ada di komputer kita masing-masing.
Ya, dapat kita lihat dari tangkapan layar di atas, bahwa program FileSyncApp menjalankan 29 Threads sekaligus bersama-sama untuk membaca, mensinkronisasi file, menampilkan progress update, dan menghandle error.
Lalu, bagaimana sih program ini berjalan? Simak video berikut ini sampai akhir.
PENUTUP
Menarik bukan? kini kita sudah mampu membuat aplikasi Java Multithread lengkap dengan User Interfacenya. Untuk selanjutnya, Anda dapat berkreasi sesuai dengan kreatifitas Anda.
Bagaimana? apakah sudah paham dengan tutorial ini? Jika Anda masih belum paham, Anda dapat meninggalkan komentar di kolom komentar postingan ini. Bahkan, jika Anda memiliki masalah pemrograman yang lain dan menarik untuk di bahas, Anda juga dapat mengirimkannya melalui kolom komentar postingan ini.
Semoga postingan bermanfaat bagi Anda para pembaca. Apabila ada pertanyaan mengenai postingan ini, Anda dapat meninggalkannya di kolom komentar. Dan, Apabila Anda menemukan artikel ini berguna, Anda dapat membagikannya. Anda juga dapat mencuplik beberapa bagian dari artikel ini, namun jangan lupa untuk sertakan URL nya. Terima kasih.