d2jsp
Log InRegister
d2jsp Forums > Off-Topic > Computers & IT > Programming & Development > Need Some Help Implementing Threads/concurrency
Add Reply New Topic New Poll
Member
Posts: 23,862
Joined: Aug 16 2006
Gold: 20.00
Oct 16 2014 02:31pm
Hey all, been awhile since I asked a question.

I know about threads/concurrency, but I have never tried implementing them.

I was tasked with creating a JAVA project for one of my classes, which among other things, displays a GUI for the user. One of the tasks my program performs is the sequential execution of a LONG list of database queries (over 30,000+).

My project works, but I don't like the fact that the GUI freezes for like 10+ seconds as it executes these queries. I was thinking I had a few options, and that the best solution would be to kind of execute the DB insertions on a separate thread.

My problem is, after searching the web for info, and having already written my code completely, I am not sure how much I would have to change in order to implement threads (I am guessing I would use the java SwingWorker utility).

Does anyone have experience doing this? If so, could you possibly take a look at my code and giving me a hint as to what I would need to change in order to make threading possible?

Any help appreciated

My code for the GUI class:

Code
import java.awt.*;
import java.util.Scanner;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import javax.swing.*;
import javax.swing.border.LineBorder;

import java.awt.event.*;
import java.io.*;

public class myGUI extends JFrame{
private static final long serialVersionUID = 1L;
private static final int WIDTH = 400;
private static final int HEIGHT = 400;

private JTextField top;
private JTextArea bottom;
private JButton openFile, loadData;

private FileHandler fh;
private DataLoader dl;

private File f;

public myGUI() {
//Set up GUI properties, initialize objects etc
top = new JTextField(30);
top.setEditable(false);
bottom = new JTextArea(14, 30);
bottom.setEditable(false);
bottom.setBorder(new LineBorder(Color.BLACK));
//Add our Buttons
openFile = new JButton("Open a file");
loadData = new JButton("Load the data");
//Add event handlers for the buttons
fh = new FileHandler();
openFile.addActionListener(fh);

dl = new DataLoader();
loadData.addActionListener(dl);

setTitle("Project 1");
//Create and set layout for our GUI
Container c = getContentPane();

c.setLayout(new FlowLayout(1, 50, 25));

bottom.setPreferredSize(new Dimension(50,200));
//Add everything to the frame
c.add(top);
c.add(openFile);
c.add(loadData);
c.add(bottom);

setSize(WIDTH, HEIGHT);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);

}

// Listener for our "Open File" button, opens file explorer, updates top text box, and saves file location
private class FileHandler implements ActionListener {
private final JFileChooser fc = new JFileChooser();

public void actionPerformed(ActionEvent e) {
if (e.getSource() == openFile) {
int val = fc.showOpenDialog(myGUI.this);

if (val == JFileChooser.APPROVE_OPTION) {
f = fc.getSelectedFile();
top.setText(f.toString());
}
}
}
}

// Listener for the "Load Data" button, calls the zipHandler() function
private class DataLoader implements ActionListener{
public void actionPerformed(ActionEvent e) {
if (e.getSource() == loadData) {
zipHandler();
}
}
}

// Function which establishes connection to DB, opens zip file(s), and executes the subsequent SQL queries
private void zipHandler() {
int count;
DBHandler db = new DBHandler();
db.createConnection();
Scanner in;

try {
ZipInputStream zin = new ZipInputStream(new FileInputStream(f));

ZipEntry zent;

while ((zent = zin.getNextEntry()) != null) {
count = 0;
bottom.append("Opening zip entry: " + zent.getName() + "...\n");
System.out.println(zent.getName());

in = new Scanner(zin);

while (in.hasNextLine()) {
String query = in.nextLine();
if (!query.isEmpty()) {
db.execQuery(query);
}
count++;
}

bottom.append("Added " + count + " rows to the database\n");
}
} catch (IOException ex) {
ex.printStackTrace();
}
db.closeDB();
}

}



Specifically, this is the function where the slow down occurs:

Code
private void zipHandler() {
int count;
DBHandler db = new DBHandler();
db.createConnection();
Scanner in;

try {
ZipInputStream zin = new ZipInputStream(new FileInputStream(f));

ZipEntry zent;

while ((zent = zin.getNextEntry()) != null) {
count = 0;
bottom.append("Opening zip entry: " + zent.getName() + "...\n");
System.out.println(zent.getName());

in = new Scanner(zin);

while (in.hasNextLine()) {
String query = in.nextLine();
if (!query.isEmpty()) {
db.execQuery(query);
}
count++;
}

bottom.append("Added " + count + " rows to the database\n");
}
} catch (IOException ex) {
ex.printStackTrace();
}
db.closeDB();
}


This post was edited by Eep on Oct 16 2014 02:38pm
Member
Posts: 1,995
Joined: Jun 28 2006
Gold: 7.41
Oct 16 2014 03:37pm
So you have two options:

Implementing Runnable
Code
public class DatabaseQueryExecutor implements Runnable
{
public void run()
{
//code you want run on a seperate thread
}
}

public class GUI
{
//...

private void doDatabaseStuff()
{
DatabaseQueryExecutor dqe = new DatabaseQueryExecutor();

new Thread(dqe).start();

}
}


Extending Thread
Code
public class DatabaseQueryExecutor extends Thread
{
public void run()
{
//code you want run on a seperate thread
}
}

public class GUI
{
//...

private void doDatabaseStuff()
{
DatabaseQueryExecutor dqe = new DatabaseQueryExecutor();

dqe.start();

}
}



These are very basic examples, but I am sure you can see how you can extend either option to benefit you.
Member
Posts: 23,862
Joined: Aug 16 2006
Gold: 20.00
Oct 16 2014 04:06pm
ah, so I would make a class for doing the DB stuff and have it implement runnable.

I was thinking that might work.

I was confused as to whether or not I needed to make the actual GUI class runnable.

Member
Posts: 1,995
Joined: Jun 28 2006
Gold: 7.41
Oct 16 2014 04:08pm
Quote (Eep @ Oct 16 2014 05:06pm)
ah, so I would make a class for doing the DB stuff and have it implement runnable.

I was thinking that might work.

I was confused as to whether or not I needed to make the actual GUI class runnable.


Design wise, I would say have a class that does your database stuff, and have a separate class that either implements a runnable or extends a thread that calls into the database class. This way you have classes with separate responsibilites.

A Class which just executes a database query shouldnt care how it is called. It's just responsible for its job. Someone else will set the rules for the invocation.
Go Back To Programming & Development Topic List
Add Reply New Topic New Poll