繁体   English   中英

如何在Java中创建这三个线程

[英]How to create these three threads in Java

我是线程的新手,对线程的了解也不多,但是我主要是在创建线程方面苦苦挣扎。

我创建了一个GUI程序,该程序使用选择排序,插入排序或合并排序对随机生成的整数数组进行重复排序。 每种排序在一个列表上进行操作,该列表的大小以2的幂增加。完成每种排序后,将显示排序的元素数及其花费的毫秒数。

我已经完成了3个课程,分别是Merge,selection和insert。

我的合并排序工作正常,但是选择和插入仍然遇到问题。 我不确定我的'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()的调用之间的差异,以获取其运行时间。

•在执行搜索之前,在Runnable中调用“ Thread.yield()”,以确保GUI线程具有根据需要更新其显示所需的优先级。

•排序完成后,应该在GUI线程中更新显示。 这可以通过在Sorter引用上调用“ displayResult”方法来完成。 该调用应在Runnable对象的run方法中进行,并作为参数传递给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
            }
        });
    }

}

我只需要有关“插入和选择”线程的帮助。 谢谢! 如果您想要他们的个人班级,这样您就可以了解他们的内心世界。

SwingUtilities.invokeLater将请求放入Swing的事件队列中,以“在将来某个时候”进行处理。 Runnable在Event Dispatching Thread的上下文中出队并执行,这意味着您的排序与UI在同一线程中运行,并将阻止它直到完成。

现在,事情变得非常复杂。 Swing不是线程安全的(这意味着您不应从事件调度线程上下文之外更新UI),并且它是单线程的,这意味着任何长时间运行或阻塞的操作都将阻止UI的更新。

“长”答案是使用为此作业设计的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);
    }

我创建这些线程的解决方案如下:

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

要求其他方法执行哪些操作,但这就是我放入线程的地方。

Thread sortContext = new Thread(new SortRunnable(*whatever args you need*));
sortContext.start();

除非您尝试从新线程更新ui,否则应该可以解决问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM