停止当前线程,然后创建一个执行相同操作的新线程?

时间:2018-08-31 09:45:05

标签: java multithreading loops runnable

我的问题是我无法弄清楚“在单击按钮时启动,而在单击另一个按钮时停止”的线程的方法,然后,如果我单击相同的启动按钮,则会启动一个新线程该操作与第一个操作完全相同。所以基本上只是一个新实例。

在我的程序中,我有一个Server应用程序,其中包含2个按钮和2个文本字段。用户输入正确的用户名和密码后,服务器应用程序将打开一个新的ServerSocket,以侦听要连接的客户端。这是在单独的线程中完成的,以防止GUI冻结。按下停止按钮后,线程停止。

当我再次在GUI中按下启动按钮时,如何使我的程序启动一个新线程,该线程与第一个线程相同?我也许必须利用循环吗?

服务器应用代码:

public class Server extends JFrame implements ActionListener {

    JLabel instructionsLabel;
    JLabel passwordLabel;
    JPasswordField passwordTF;
    JButton shutdownButton;
    JButton startupButton;
    JLabel usernameLabel;
    JTextField usernameTF;
    Thread MyThread = new Thread(new ServerRunnable());

    public Server() {
        super("Server");
        initComponents();
    }
                               // My problem is here
    public void starterMeth() {
        MyThread.start();
    }

    public void stopMeth() {
        MyThread.interrupt();
    }
                                // in these 2 methods
    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();

        String f = "n";
        ConnectionBean cb = new ConnectionBean();

        char[] a = passwordTF.getPassword();
        String b = new String(a);
        String inputDetails = usernameTF.getText() + b;

        Iterator it = cb.getDetails().iterator();
        while (it.hasNext()) {
            Object next = it.next();
            if (inputDetails.equals(next)) {
                f = "y";
                if (source == startupButton) {
                    if (!MyThread.isInterrupted()) {
                        starterMeth();
                        JOptionPane.showMessageDialog(null,
                            "Congratulations! Server started.",
                            "Start-up Message",
                            JOptionPane.INFORMATION_MESSAGE);
                    } else {
                        JOptionPane.showMessageDialog(null,
                            "Please restart the server application.",
                            "Start-up Message",
                            JOptionPane.INFORMATION_MESSAGE);
                    }
                } else if (source == shutdownButton) {
                    stopMeth();
                    JOptionPane.showMessageDialog(null,
                        "Server shut-down successfully!",
                        "Shut-down Message",
                        JOptionPane.INFORMATION_MESSAGE);
                }
                // only resets the text fields when the correct details are entered
                passwordTF.setText("");
                usernameTF.setText("");
            }
        }
        if (f.equals("n")) {
            JOptionPane.showMessageDialog(null, "Invalid username or password.", "Alert", JOptionPane.WARNING_MESSAGE);
        }
        cb.setCloseConnection(true);
    }

    private void initComponents() {
    }
}

我的可运行代码:

public class ServerRunnable implements Runnable {

    @Override
    public void run() {

        try {
            ServerSocket ss = new ServerSocket(7777);

            while(true) {
                Socket cs = ss.accept();
                new ClientThread(cs).start();
        }
        } catch (IOException ex) {
        }
    }
}

2 个答案:

答案 0 :(得分:1)

概述

尽管thread的创建在Java中是有效的,但出于多种原因,强烈建议不要创建它。最重要的一点是,创建thread的成本很高且占用大量资源。另外,在标准库中实现了许多更安全/有效的模型,可以用来简化问题。在这种特殊情况下,由于操作的性质,我建议您不要执行此操作。 开始-停止重复发生。请注意,thread一旦启动就无法重新启动,并且在执行时停止线程的唯一方法是调用interrupt()。不幸的是,中断线程需要开发人员在run()方法中实现错误处理。下面,我们将看到run()Runnable实现的Thread方法。

public void run() {
    try {
        // Your connection logic would be here
        yourLogic();
    } catch (InterruptedException ie) {
        Thread.currentThread().interrupt(); // Maintain status
    }
}

让我们假设您做了自己的名为thread的{​​{1}}实现。下面我们将看到如何利用它:

MyThreadImpl

或者,如果您像在此应用程序中一样实现自己的public void starterMeth() { Thread myThread = new MyThreadImpl(); // Create thread myThread.start(); // Start execution in parallel } public void stopMeth() { myThread.interrupt(); // Stop the thread } ,它将看起来像这样:

Runnable

尽管这两个都是有效的,但是有更好的方法。

更好的方法

我的建议是由于CompletableFuture类的强大实现和合意的控制,因此可以使用它。 CompletableFutures利用全局public void starterMeth() { Thread myThread = new Thread(new ServerRunnable()); // Create thread myThread.start(); // Start execution in parallel } public void stopMeth() { myThread.interrupt(); // Stop the thread } 进行线程处理,以便应用程序可以更高效地执行。另外,您可以收到对象内的Future供以后使用,而不必每次尝试重新创建它。让我们研究一下此实现的工作原理:

ForkJoinPool.common()

答案 1 :(得分:0)

Java 不允许 重新启动线程,一旦其 完成执行

中断您创建的线程将仅完成其执行。这里的问题是您使用的是已完成执行的同一线程(一旦单击了停止按钮)。

我建议以下其中一项:

  1. 改善您的可运行性,以便当用户尝试单击 shutdownButton 按钮时,它将停止正在执行的操作,并获取某种信号量以使其“处于睡眠状态” ”,直到再次按下 startupButton
  2. (更容易)始终在 starterMeth 上创建一个新线程。不要忘记在启动新线程之前检查线程是否正在运行并中断它。

我希望这会有所帮助。