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

标签 java multithreading loops runnable

我的问题是,我无法找到一种方法来让线程“单击一个按钮时启动,单击另一个按钮时停止”,然后如果我单击同一个开始按钮,则会启动一个新线程它执行与第一个完全相同的操作。所以基本上只是一个新实例。

在我的程序中,我有一个服务器应用程序,它有 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) {
        }
    }
}

最佳答案

概述

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

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

假设您创建了自己的线程实现,名为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,则它将如下所示:

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
}

虽然这两种方法都是有效的,但还有更好的方法。

更好的方法

我的建议是利用CompletableFuture类由于其强大的实现和理想的控制。 CompletableFutures 利用全局 ForkJoinPool.common() 进行线程处理,以便应用程序可以更高效地执行。此外,您还可以收到Future它位于对象内供以后使用,而不是每次都尝试重新创建它。下面让我们研究一下这个实现是如何工作的:

public class Server {
    CompletableFuture<Void> myFuture;
    ...

    public void starterMeth() {
        myFuture = new CompletableFuture<Void>(); // Create future
        myFuture.runAsync(new ServerRunnable()); // Start execution in parallel
    }

    public void stopMeth() {
        myFuture.cancel(true); // Stop the future
    }

    ...
}

关于java - 停止当前线程,然后创建一个执行相同操作的新线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52112709/

相关文章:

java - 解密时最初的几个字符被截断

java - JPA 序列生成器不工作

java - 从结构数组中提取字段的 GenericUDF 函数

java - newCachedThreadPool 是如何复用线程的?

java - 如何根据线程的名称或 ID 向线程发送通知?是否可以?

具有 2 个通用参数的 Java 类

java - 缓冲 VBO 数据的小延迟

actionscript-3 - 在这种情况下如何循环 timelinemax 动画

java - 无限循环;不明白怎么办

javascript - 如何一次执行一个循环语句(jQuery)?