I am new to threads, and I don't know much about them, however I am struggling with creating them mainly.
I created a GUI program that repeatedly sorts a randomly generated array of ints using either selection sort, insertion sort, or merge sort. Each sort operates on a list whose size is raised by a power of 2. Upon completion of each sort, the number of elements sorted and the number of milliseconds it took is displayed.
I have 3 classes already done, they are Merge, selection, and insertion.
My Merge sort is working correctly, however I am still having trouble with the selection and insertion. I'm not sure if my 'if' and 'else' statements are incorrect, or if the threads themselves are wrong, but I am struggling with them.
Here's what I have in my Main class.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class Sorter extends JFrame
{
private static final long serialVersionUID = 1L;
private static final int WIDTH = 400;
private static final int HEIGHT = 300;
public static final String SELECTION_SORT_TEXT = "Selection Sort";
public static final String INSERTION_SORT_TEXT = "Insertion Sort";
public static final String MERGE_SORT_TEXT = "Merge Sort";
private JComboBox sortingAlgorithms;
private JTextArea display;
private JButton sortButton;
private JPanel panel;
private JLabel loadingIcon;
private JLabel sort;
private String[] options = {SELECTION_SORT_TEXT, INSERTION_SORT_TEXT, MERGE_SORT_TEXT};
public Sorter()
{
setTitle("Sorter");
setSize(WIDTH, HEIGHT);
setLayout(new BorderLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
createContents();
setVisible(true);
}
private void createContents()
{
//TODO: Implement
this.panel = new JPanel(new FlowLayout());
this.display = new JTextArea();
this.loadingIcon = new JLabel(new ImageIcon("loading.gif"));
this.sort = new JLabel("Sorting Algorithm");
this.sortButton = new JButton("Sort");
this.sortingAlgorithms = new JComboBox<>(options);
loadingIcon.setSize(25,25);
display.setBorder(new EmptyBorder(10,10,10,10));
panel.add(sort);
panel.add(sortingAlgorithms);
panel.add(sortButton);
panel.add(loadingIcon);
sortButton.addActionListener(new SortButtonListener());
loadingIcon.setVisible(false);
display.setEnabled(false);
setLayout(new BorderLayout());
add(panel, BorderLayout.NORTH);
add(display, BorderLayout.CENTER);
}
private class SortButtonListener implements ActionListener
{
private int[] arr;
private SortRunnable sr;
public void actionPerformed(ActionEvent e)
{
sr.run();
ExecutorService es = Executors.newSingleThreadExecutor();
//TODO: Finish Implementation
if(e.getSource() == sortButton)
{
sortingAlgorithms.setEnabled(false);
sortButton.setEnabled(false);
loadingIcon.setVisible(true);
display.setText("N\t\tRuntime (ms)");
}
arr = new int [2000];
for(int i = 0; i <= 8; i++)
{
arr = new int [(int) Math.pow(2, i) * 1000];
fillArr();
sr = new SortRunnable((String) sortingAlgorithms.getSelectedItem(), arr, Sorter.this);
es.execute(sr);
}
Thread sortContext = new Thread(new SortRunnable((String)
sortingAlgorithms.getSelectedItem(), arr, Sorter.this));
sortContext.start();
es.shutdown();
}
/*
These values are powers of 2 from 0 to 8, times 1000.
*/
private void fillArr()
{
Random r = new Random();
int n = 0;
for(int i=0; i<arr.length; ++i)
{
arr[i] = r.nextInt();
}
}
}
/*
The displayResult method is responsible for adding the provided sort runtime information to
the display. It should also check to see if the final sort runtime information is present. If so,
it should hide the loading gif and enable the JComboBox and sort button.
*/
public synchronized void displayResult(int n, long runtime)
{
//TODO: Implement
display.append("\n" + n + "\t\t" + runtime);
}
public static void main(String[] args)
{
new Sorter();
}
}
I am not too concerned with what's above. I am more concerned on how to create my thread in my SortRunnable class which these threads are created. Here is what is expected from this class.
This class contains the code used to time and execute the selected sort.
• You can find the difference between calls to System.currentTimeMillis() at the start end end of the sort to get its runtime.
• Call "Thread.yield()" in the Runnable before the search is executed to ensure that the GUI thread has the priority required to update its display as needed.
• When the sort has finished, the display should be updated in the GUI thread. This can be accomplished by calling the "displayResult" method on the Sorter reference. This call should occur within the Runnable object's run method, passed as an argument to SwingUtilities invokeLater method, as in:
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
//call Sorter's displayResult method here
}
});
Here is my code in there that I need help in.
import javax.swing.*;
public class SortRunnable implements Runnable
{
private String sortingAlgorithm;
private int[] arr;
private Sorter sorter;
public SortRunnable(String sortingAlgorithm, int[] arr, Sorter sorter)
{
this.sortingAlgorithm = sortingAlgorithm;
this.arr = arr;
this.sorter = sorter;
}
@Override
public void run()
{
Thread.yield();
if(sortingAlgorithm.equals(sorter.MERGE_SORT_TEXT))
{
MergeSort.mergeSort(arr);
}
Thread.yield();
if(sortingAlgorithm.equals(sorter.SELECTION_SORT_TEXT))
{
SelectionSort.sort(arr);
}
Thread.yield();
if(sortingAlgorithm.equals(sorter.INSERTION_SORT_TEXT))
{
InsertionSort.sort(arr);
}
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
Thread.yield();
sorter.displayResult(arr.length, System.currentTimeMillis());
//call Sorter's displayResult method here
}
});
}
}
I just need help with the Insertion and Selection thread. Thank you! If you would like their individual classes so you can see what's inside of them let me know.
My solution on creating these threads go as following:
In the sortRunnable class:
public void run()
{
long store = System.currentTimeMillis();
if(sortingAlgorithm.equals(sorter.MERGE_SORT_TEXT))
{
MergeSort.mergeSort(arr);
}
if(sortingAlgorithm.equals(sorter.SELECTION_SORT_TEXT))
{
SelectionSort.sort(arr);
}
if(sortingAlgorithm.equals(sorter.INSERTION_SORT_TEXT))
{
InsertionSort.sort(arr);
}
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
sorter.displayResult(arr.length, System.currentTimeMillis()-store);
//call Sorter's displayResult method here
}
});
}
That's where I created my threads.
On my other class, I put them in as following:
private class SortButtonListener implements ActionListener
{
private int[] arr;
private SortRunnable sr;
public void actionPerformed(ActionEvent e)
{
ExecutorService es = Executors.newSingleThreadExecutor();
//TODO: Finish Implementation
if(e.getSource() == sortButton)
{
sortingAlgorithms.setEnabled(false);
sortButton.setEnabled(false);
loadingIcon.setVisible(true);
display.setText("N\t\tRuntime (ms)");
}
arr = new int [2000];
for(int i = 0; i <= 8; i++)
{
arr = new int [(int) Math.pow(2, i) * 1000];
fillArr();
sr = new SortRunnable((String) sortingAlgorithms.getSelectedItem(), arr, Sorter.this);
es.execute(sr);
}
es.shutdown();
}
private void fillArr()
{
Random r = new Random();
for(int i=0; i<arr.length; ++i)
{
arr[i] = r.nextInt();
}
}
}
Which the other methods was asked to do, but that's where I put in my threads.