Как создать эти три потока в Java - PullRequest
0 голосов
/ 16 апреля 2019

Я новичок в темах и мало о них знаю, однако я в основном изо всех сил стараюсь их создавать.

Я создал программу с графическим интерфейсом, которая многократно сортирует произвольно сгенерированный массив целых чисел, используя сортировку выбора, вставку или сортировку слиянием. Каждая сортировка работает со списком, размер которого увеличивается на степень 2. По завершении каждой сортировки отображается количество отсортированных элементов и количество необходимых миллисекунд.

У меня уже есть 3 класса, это слияние, выделение и вставка.

Моя сортировка слиянием работает правильно, однако у меня все еще возникают проблемы с выделением и вставкой. Я не уверен, что мои операторы 'if' и 'else' неверны или сами потоки неверны, но я борюсь с ними.

Вот что я имею в своем основном классе.

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();
 }
}

Я не слишком обеспокоен тем, что выше. Я больше обеспокоен тем, как создать мой поток в моем классе SortRunnable, в котором создаются эти потоки. Вот что ожидается от этого класса.

Этот класс содержит код, используемый для определения времени и выполнения выбранной сортировки.

• Вы можете найти разницу между вызовами System.currentTimeMillis () в начале и в конце сортировки, чтобы получить ее время выполнения.

• Вызвать «Thread.yield ()» в Runnable перед выполнением поиска, чтобы убедиться, что поток GUI имеет приоритет, необходимый для обновления своего отображения по мере необходимости.

• По завершении сортировки отображение должно быть обновлено в потоке графического интерфейса. Это можно сделать, вызвав метод displayResult для ссылки на сортировщик. Этот вызов должен происходить внутри метода run объекта Runnable, передаваемого в качестве аргумента методу SwingUtilities invokeLater, например:

 SwingUtilities.invokeLater(new Runnable() 
 {
 @Override
 public void run() 
 {
   //call Sorter's displayResult method here
 }
 });

Вот мой код, в котором мне нужна помощь.

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
            }
        });
    }

}

Мне просто нужна помощь с темой Вставка и Выбор. Спасибо! Если вы хотите, чтобы их индивидуальные занятия, чтобы вы могли видеть, что внутри них, дайте мне знать.

Ответы [ 3 ]

1 голос
/ 16 апреля 2019

SwingUtilities.invokeLater помещает запрос в очередь событий Swing для обработки "в какой-то момент в будущем". Runnable исключается из очереди и выполняется в контексте потока диспетчеризации событий, что означает, что сортировка выполняется в том же потоке, что и пользовательский интерфейс, и будет блокировать его до завершения.

Теперь вот где все становится действительно сложно. Swing НЕ является поточно-ориентированным (то есть вы не должны обновлять пользовательский интерфейс вне контекста потока диспетчеризации событий) и является однопоточным, то есть любые длительные или блокирующие операции будут препятствовать обновлению пользовательского интерфейса.

«Длинный» ответ: используйте SwingWorker, который предназначен для этой работы. Тем не менее, вы можете продолжать использовать свой код, но он немного более грязный.

Вам необходимо собрать еще несколько деталей, например, когда сортировка была начата и когда сортировка закончилась. Затем вам нужно вычислить разницу между этими двумя точками во времени в миллисекундах.

Существует множество способов, которыми вы можете «сделать» это, но, поскольку Java теперь поддерживает прекрасный новый API даты / времени, вы могли бы также начать использовать его.

Эта информация затем передается обратно в пользовательский интерфейс, может быть, что-то вроде ...

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()
    {
        LocalDateTime startTime = LocalDateTime.now();
        MergeSort.mergeSort(arr);
        LocalDateTime endTime = LocalDateTime.now();
        long diff = ChronoUnit.MILLIS.between(startTime, endTime)
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                sorter.displayResult(arr.length, diff);
            }
        });
    }

}

Хорошо, следующая проблема, вы не используете ExecutorService.

Во-первых, это действительно должно быть поле экземпляра, так как вам не нужно создавать дополнительные экземпляры.

Во-вторых, ваша логика повсюду, в основном вы хотите ...

  1. Создать экземпляр Sorter
  2. Заполнить массив
  3. Создать экземпляр SortRunnable
  4. Передать SortRunnable в ExecutorService, чтобы его можно было выполнить ...

Может быть, что-то вроде ...

private ExecutorService es = Executors.newSingleThreadExecutor();
public void actionPerformed(ActionEvent e)
{
    fillArr();
    Sorter sorter = null;
    String algorthim = null;
    if(e.getSource() == options[0])
    {
        // create the instance of Sorter to be used...
        sorter = ...
        algorthim = ...
    }
    if(e.getSource() == options[1])
    {
        // create the instance of Sorter to be used...
        sorter = ...
        algorthim = ...
    }
    if(e.getSource() == options[2])
    {
        // create the instance of Sorter to be used...
        sorter = ...
        algorthim = ...
    }
    if (sorter != null) {
        SortRunnable sr = new SortRunnable(algorthim, arr, sorter)
        es.submit(sr);
    }
1 голос
/ 21 апреля 2019

Мое решение по созданию этих тем состоит в следующем:

В классе sortRunnable:

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
            }
        });
    }

Вот где я создал свои темы.

В другом классе я вставил их следующим образом:

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();
        }
    }
}

Что другие методы попросили сделать, но это то, куда я положил свои темы.

0 голосов
/ 16 апреля 2019
Thread sortContext = new Thread(new SortRunnable(*whatever args you need*));
sortContext.start();

должен сделать трюк, если вы не попытаетесь обновить пользовательский интерфейс из нового потока.

...