线程没有停止使用标志为volatile

时间:2016-09-05 11:18:26

标签: java multithreading

在下面的代码中我试图使用java applet启动和停止服务器按钮.Start使用线程很好但我想停止服务器上的按钮。我使用了 volatile 变量。我没有让服务器停止..

这是代码:

public class TCPServer extends Thread {
    public static final int SERVERPORT = 8002;
    private boolean running = false;
    public volatile boolean stop = false;
    public Socket client = null;

    public static void main(String[] args) {
        ServerBoard frame = new ServerBoard();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public void run() {
        super.run();
        running = true;
        try {
            System.out.println("Server Has Started........ \n Waiting for client........");
            ServerSocket serverSocket = new ServerSocket(SERVERPORT);
            try {
                while (!stop && running) {
                    client = serverSocket.accept();
                    System.out.println("Connection Accepted......");
                    BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
                    String usercmnd = in.readLine();
                    if (usercmnd != null) {
                        Runtime runtime = Runtime.getRuntime();
                        Process p = runtime.exec(usercmnd);
                    }
                }
                if (stop) {
                    serverSocket.close();
                    client.close();
                    System.out.println("Server Has Stopped");
                    System.exit(0);
                }

            } catch (Exception e) {
                System.out.println("Error");
                e.printStackTrace();
            }
        } catch (Exception e) {
            System.out.println("Error");
            e.printStackTrace();
        }

    }

    public void requestStop() {
        stop = true;
    }
}

但每当我点击停止服务器的停止按钮时,它就不会像我所期望的那样在控制台上显示任何输出。它也没有显示任何错误 这是停止代码

stopServer = new JButton("Stop");
stopServer.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        stopServer.setEnabled(false);
        startServer.setEnabled(true);
        mServer = new TCPServer();
        mServer.requestStop();

    }
});

5 个答案:

答案 0 :(得分:4)

它不会停止,因为您在停止之前创建了一个新实例,并且当您应该在当前{{1}实例上调用requestStop()时,您甚至不首先启动它}。

TCPServer

答案 1 :(得分:0)

在停止按钮的ActionListener实现中,您正在访问TCPServer的另一个实例(因为您正在创建一个新实例)。所以你设置值"停止"到第二个对象。它对使用开始按钮创建的第一个实例没有影响。

尝试在两个按钮的动作侦听器实现之外实例化TCServer,并为这两个按钮使用该单个实例。

答案 2 :(得分:0)

由于https://docs.oracle.com/javase/7/docs/api/java/net/ServerSocket.html#accept()

ServerSocket::accept是一种阻止方法,因此只能在成功连接之间检查stop变量。

您可以使用ServerSocket(并捕获ServerSocket::setSoTimeout)或SocketTimeoutException服务器线程设置interrupt超时并捕获InterruptedException

两个例外都将从ServerSocket::accept抛出。

请注意,线程中断优先于超时和重复异常捕获。

答案 3 :(得分:0)

试试这个:

public void requestStop() {
    stop = true;
    interrupt();
}

但是,在这种情况下,我们无法保证,已经处理的逻辑将成功关闭。

此外,您尝试为TCPServer的新实例调用requestStop,而不是已存在。

答案 4 :(得分:0)

您的代码client = serverSocket.accept();正在阻止。所以一旦你点击了" stopServer"按钮,您请求停止,但只有在客户端向服务器发送下一个请求时才会对其执行操作。你需要做的是在一个单独的线程中运行你的方法run()中的逻辑并捕获InterruptedException和ClosedByInterruptException并清理并返回那里。在你的stopButton上单击,你将在你的线程上调用interrupt()方法。在here

中了解相关信息