当前位置:  开发笔记 > 编程语言 > 正文

多线程和Java Swing问题

如何解决《多线程和JavaSwing问题》经验,为你挑选了1个好方法。

嗨,我有一个工作正常的GUI应用程序.我创建了一个套接字服务器 当我在程序中创建Server类的新对象时,GUI应用程序停止响应.

这是我的服务器类.如果我做

Server s = new Server();

在我的主应用程序中它停止工作.我应该如何添加它?制作一个新帖子?我试过了

Thread t = new Thread(new Server());
t.start();

但问题仍然存在.拜托,我将非常感谢你的帮助.

package proj4;

import java.net.*; 
import java.io.*; 

public class Server implements Runnable { 
    ServerSocket       serverSocket = null;
    Socket             clientSocket = null;
    ObjectOutputStream out          = null;
    ObjectInputStream  in           = null;
    int                port;
    static int         defaultPort  = 30000;
    boolean            isConnected  = false;
    Thread             thread;
    DataPacket         packet       = null;

    public Server(int _port) {
        try {
            serverSocket = new ServerSocket(_port);
            serverSocket.setSoTimeout(1000*120);  //2 minutes time out     
            isConnected = true;
            System.out.println("server started successfully");
            thread = new Thread(this);
            thread.setDaemon(true);
            //thread.run();
        } catch (IOException e) {
            System.err.print("Could not listen on port: " + port);
            System.exit(1);
        }
        try {
            System.out.println("Waiting for Client");
            clientSocket = serverSocket.accept();
            System.out.println("Client Connected");
            thread.run();
        } catch (IOException e) {
            System.err.println("Accept failed.");
            System.exit(1);
        }
        try {
            out = new ObjectOutputStream(clientSocket.getOutputStream());
            System.out.println("output stream created successfully");
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            in = new ObjectInputStream(clientSocket.getInputStream());
            System.out.println("input stream created successfully");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Server() {
        this(defaultPort); //server listens to port 30000 as default
    }

    public void run() {
        System.out.println("Thread running, listening for clients");//debugging purposes
        while (isConnected) {
            try {
                packet = this.getData();
                Thread.sleep(0);
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
        }
    } 

    public DataPacket getData() {
        try {
            packet = (DataPacket)in.readObject();
        } catch (Exception ex)  {
            System.out.println(ex.getMessage());
        }
        return packet;
    }

    public void sendData(DataPacket dp) {
        try {
            out.writeObject(dp);
        } catch (IOException e) {
            e.printStackTrace();
        } 
        try {
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void closeConnection() throws IOException {
        out.close(); 
        in.close(); 
        clientSocket.close(); 
        serverSocket.close(); 
    }
} 

Eddie.. 11

您的Server构造函数可能无限期地阻塞accept().

关于Swing程序的两件事:

    永远不要在Swing事件线程中执行任何长任务,并且,

    除非将正在使用的方法明确记录为线程安全,否则永远不要操作Swing事件线程之外的任何Swing对象.

这意味着如果服务器是从Swing事件线程启动的 - 也就是说,如果它是为响应按钮单击等而启动的 - 那么是的,您必须为您的Server对象生成另一个线程.否则,您保证在您的线程退出之前阻止Swing事件线程.

您说即使您为服务器生成另一个线程,您的应用程序仍然停止响应?确保你正在打电话Thread.start()而不是run(),或者你不小心通过在自己的线程中运行"新线程"来阻止自己.

笔记:

    我看到你Thread.sleep(0);在run()循环中执行了一个操作.这不能保证做任何事情.如果你有一台CPU机器,这可以公平地实现为无操作,允许同一个线程继续运行.

    你真的想isConnected成为volatile- 否则不能保证除了改变之外的任何线程都会看到对这个变量的更改.

    您不会isConnected在任何地方设置为false,因此您run()将一直运行直到JVM停止或直到该线程采用RuntimeException.

    不鼓励在构造函数中启动Threads.(参见Java Concurrency In Practice.)

    在你使用Thread的方法之前,你不想accept在你ServerSocket身上run()!否则,您的构造函数将阻止等待连接,并且不会将控制权返回给事件线程!

    您的构造函数中包含以下代码:

你的代码是:

thread = new Thread(this);
thread.setDaemon(true);
//thread.run();

当你thread.run()没有注释掉时,你没有开始新的线程!要做到这一点,你需要这样做thread.start().相反,你在调用构造函数的同一个线程中运行这个新的Thread(它永远不会停止,因为上面的原因#3).现在编写代码的方式,所有IOExceptions都会被记录,但是否则会被吞噬.您可能希望设置isConnectedfalseon IOException,以及in closeConnection().



1> Eddie..:

您的Server构造函数可能无限期地阻塞accept().

关于Swing程序的两件事:

    永远不要在Swing事件线程中执行任何长任务,并且,

    除非将正在使用的方法明确记录为线程安全,否则永远不要操作Swing事件线程之外的任何Swing对象.

这意味着如果服务器是从Swing事件线程启动的 - 也就是说,如果它是为响应按钮单击等而启动的 - 那么是的,您必须为您的Server对象生成另一个线程.否则,您保证在您的线程退出之前阻止Swing事件线程.

您说即使您为服务器生成另一个线程,您的应用程序仍然停止响应?确保你正在打电话Thread.start()而不是run(),或者你不小心通过在自己的线程中运行"新线程"来阻止自己.

笔记:

    我看到你Thread.sleep(0);在run()循环中执行了一个操作.这不能保证做任何事情.如果你有一台CPU机器,这可以公平地实现为无操作,允许同一个线程继续运行.

    你真的想isConnected成为volatile- 否则不能保证除了改变之外的任何线程都会看到对这个变量的更改.

    您不会isConnected在任何地方设置为false,因此您run()将一直运行直到JVM停止或直到该线程采用RuntimeException.

    不鼓励在构造函数中启动Threads.(参见Java Concurrency In Practice.)

    在你使用Thread的方法之前,你不想accept在你ServerSocket身上run()!否则,您的构造函数将阻止等待连接,并且不会将控制权返回给事件线程!

    您的构造函数中包含以下代码:

你的代码是:

thread = new Thread(this);
thread.setDaemon(true);
//thread.run();

当你thread.run()没有注释掉时,你没有开始新的线程!要做到这一点,你需要这样做thread.start().相反,你在调用构造函数的同一个线程中运行这个新的Thread(它永远不会停止,因为上面的原因#3).现在编写代码的方式,所有IOExceptions都会被记录,但是否则会被吞噬.您可能希望设置isConnectedfalseon IOException,以及in closeConnection().

推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有