2021-04-26

线程池一个游戏

输出结果

客户端设计

客户机代码

package cn.edu.ldu;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import javax.swing.JOptionPane;


public class ClientUI extends javax.swing.JFrame {
    private Socket clientSocket=null; //客户机套接字
    private BufferedReader in; //网络输入流
    private PrintWriter out; //网络输出流

    /**
     * Creates new form ClientUI
     */
    public ClientUI() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        topPanel = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        txtRemoteName = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        txtRemotePort = new javax.swing.JTextField();
        btnConnect = new javax.swing.JButton();
        midPanel = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        txtArea = new javax.swing.JTextArea();
        txtInput = new javax.swing.JTextField();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        topPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("连接服务器面板"));

        jLabel1.setText("服务器主机名");

        txtRemoteName.setText("localhost");

        jLabel2.setText("服务器端口");

        txtRemotePort.setText("5000");

        btnConnect.setText("连接服务器");
        btnConnect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnConnectActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout topPanelLayout = new javax.swing.GroupLayout(topPanel);
        topPanel.setLayout(topPanelLayout);
        topPanelLayout.setHorizontalGroup(
            topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(topPanelLayout.createSequentialGroup()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(txtRemoteName, javax.swing.GroupLayout.PREFERRED_SIZE, 143, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(40, 40, 40)
                .addComponent(jLabel2)
                .addGap(18, 18, 18)
                .addComponent(txtRemotePort, javax.swing.GroupLayout.PREFERRED_SIZE, 131, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(61, 61, 61)
                .addComponent(btnConnect)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        topPanelLayout.setVerticalGroup(
            topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(topPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(txtRemoteName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel2)
                    .addComponent(txtRemotePort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btnConnect))
                .addContainerGap(64, Short.MAX_VALUE))
        );

        getContentPane().add(topPanel, java.awt.BorderLayout.PAGE_START);

        midPanel.setLayout(new java.awt.BorderLayout());

        txtArea.setColumns(20);
        txtArea.setRows(5);
        txtArea.setBorder(javax.swing.BorderFactory.createTitledBorder("客户机对话面板,客户机扮演“门内人”角色"));
        jScrollPane1.setViewportView(txtArea);

        midPanel.add(jScrollPane1, java.awt.BorderLayout.CENTER);

        txtInput.setText("此处输入回话内容...");
        txtInput.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                txtInputFocusGained(evt);
            }
        });
        txtInput.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                txtInputActionPerformed(evt);
            }
        });
        midPanel.add(txtInput, java.awt.BorderLayout.PAGE_END);

        getContentPane().add(midPanel, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>                        

    private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {                                           
        // TODO add your handling code here:
        try {
            //获取参数
            String remoteName=txtRemoteName.getText();
            int remotePort=Integer.parseInt(txtRemotePort.getText());
            //构建套接字格式地址
            SocketAddress remoteAddr=new InetSocketAddress(remoteName,remotePort);
            //1. 创建套接字clientSocket(Socket)并连接到远程服务器
            clientSocket=new Socket();            
            clientSocket.connect(remoteAddr);
            //2. 创建绑定到套接字clientSocket上的网络输入流与输出流
            in=new BufferedReader(new InputStreamReader(clientSocket.getInputStream(),"UTF-8"));
            out=new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream(),"UTF-8"),true);      
            String fromOutdoor=in.readLine();//接受服务器消息
            txtArea.append("outdoor: "+fromOutdoor+"\n"); //显示服务器消息       
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, ex.getMessage(), "连接错误", JOptionPane.ERROR_MESSAGE);
            return;
        } 
        txtRemoteName.setEnabled(false);
        txtRemotePort.setEnabled(false);
        btnConnect.setEnabled(false);
    }                                          

    private void txtInputActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
        String fromOutdoor;
        String fromIndoor;
        if (clientSocket==null) {
            JOptionPane.showMessageDialog(null, "请先连接服务器!", "连接错误", JOptionPane.ERROR_MESSAGE);
            return;
        }
        try {
            fromIndoor=txtInput.getText();
            if (!fromIndoor.equals("")) {
                out.println(fromIndoor);
                txtArea.append("indoor: "+fromIndoor+"\n");
                txtInput.setText("");
            } else {
                JOptionPane.showMessageDialog(null, "问话内容为空,请重新输入!", "输入错误", JOptionPane.ERROR_MESSAGE);
                return;
            }//end if
            fromOutdoor=in.readLine();
            txtArea.append("outdoor: "+fromOutdoor+"\n");
            if (fromOutdoor.endsWith("Goodbye!")) {
                txtRemoteName.setEnabled(true);
                txtRemotePort.setEnabled(true);
                btnConnect.setEnabled(true);//激活按钮
                //4. 关闭并销毁网络流
                //5. 关闭并销毁套接字
                try { 
                    if (in!=null) in.close();
                    if (out!=null) out.close();
                    if (clientSocket!=null)clientSocket.close();    
                } catch (IOException ex) {  }         
            }//end if
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, ex.getMessage(), "接收数据错误", JOptionPane.ERROR_MESSAGE);
        }//end try
    

    }                                        

    private void txtInputFocusGained(java.awt.event.FocusEvent evt) {                                     
        // TODO add your handling code here:
        txtInput.setText("");
    }                                    

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(ClientUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(ClientUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(ClientUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(ClientUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ClientUI().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton btnConnect;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JPanel midPanel;
    private javax.swing.JPanel topPanel;
    private javax.swing.JTextArea txtArea;
    private javax.swing.JTextField txtInput;
    private javax.swing.JTextField txtRemoteName;
    private javax.swing.JTextField txtRemotePort;
    // End of variables declaration                   
}

//处理与客户机的数据交换ClientThread 继承 Thread

package cn.edu.ldu;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.List;
import javax.swing.SwingWorker;

/**
 *
 * @author World
 */
//处理与客户机的数据交换
public class ClientThread extends Thread {
    private final Socket toClientSocket; //与客户机对话的套接字
    private BufferedReader in; //网络输入流
    private PrintWriter out; //网络输出流
    private Protocol protocol; //会话协议    
    private int clientCounts; //客户机数量   
    public ClientThread(Socket toClientSocket,int clientCounts) { //构造函数
        this.toClientSocket=toClientSocket;
        this.clientCounts=clientCounts;
    }
    @Override
   public void run() {
        try {
            //创建绑定到套接字toClientSocket上的网络输入流与输出流
            in=new BufferedReader(new InputStreamReader(toClientSocket.getInputStream(),"UTF-8"));
            out=new PrintWriter(new OutputStreamWriter(toClientSocket.getOutputStream(),"UTF-8"),true);
            long currentId=Thread.currentThread().getId();
            ServerUI.txtArea.append("当前会话线程ID:"+currentId+"\n"); //发布到process
            //根据服务器协议,在网络流上进行读写操作
            protocol=new Protocol(); //生成协议对象
            String outdoorStr; //门外人的回答
            String indoorStr; //门内人的问话
            outdoorStr=protocol.protocolWorking(null); //根据协议生成门外人的问话
            out.println(outdoorStr); //向客户机发起会话
            ServerUI.txtArea.append("outdoor"+clientCounts+":"+outdoorStr+"\n"); //发布门外人的话到process处理        
            while ((indoorStr=in.readLine())!=null) { //只要客户机不断开连接则反复读
                ServerUI.txtArea.append("indoor"+clientCounts+":"+indoorStr+"\n");  //发布门内人的话到process处理
                //根据协议生成回答消息
                outdoorStr=protocol.protocolWorking(indoorStr);
                out.println(outdoorStr); //向客户机发送回答
                ServerUI.txtArea.append("outdoor"+clientCounts+":"+outdoorStr+"\n"); //发布门外人的话到process处理
                if (outdoorStr.endsWith("Goodbye!")) //结束游戏
                    break;
            }//end while 
            ServerUI.clientCounts--;  //客户机总数减1
            //因为客户机断开了连接,所以释放资源
            if (in!=null) in.close();
            if (out!=null) out.close();
            if (toClientSocket!=null) toClientSocket.close();
        } catch (IOException ex) {}
    }//end run 
}//end class ClientThread

//游戏内的设计

package cn.edu.ldu;

public class Protocol {
    //游戏包含敲门人和门内人两个角色。门内人的问话和回答有固定格式,敲门人的回答是变化的,所以用以下常量表示敲门人会话进程和状态
    //游戏状态
    private static final int WAITING=0; //等待 游戏还未开始
    private static final int SENTKNOCKKNOCK=1; //敲门完成 服务器向客户机发送Knock
    private static final int SENTCLUE=2; //第一遍线索回答完成 服务器向客户机发送单词线索
    private static final int SENTANSWER=3; //第二遍终极回答完成 服务器向客户机发送幽默回答
    private static final int NUMJOKES=8; //游戏总局数  
    private int state=WAITING; //会话状态
    private int currentJoke=0; //计数
    //以下两个数组分别存储敲门人的两次回答
    private String[] clues={"Buster","Orange","Ice cream","Tunis","Old lady","Yah","Dishes","Amish"};//单词线索
    private String[] answers={"Buster Cherry! Is your daughter home?","Orange you going to answer the door?","Ice cream if you don't let me in!",
        "Tunis company, three's a crowd!","Wow I didn't know you could yodel.",
        "Naaah, bro, I prefer google.","Dishes the Police come out with your hands up.","Awwww How sweet. I miss you too."};//幽默回答
    public String protocolWorking(String question) { //question门内人的问话客户机  String服务器
        String answer=null; //敲门人的回答
        switch (state) {
            case WAITING: //开始敲门
                answer="Knock! Knock!";
                state=SENTKNOCKKNOCK;
                break;
            case SENTKNOCKKNOCK: //谁在敲门?问答
                if (question.equalsIgnoreCase("Who's there?")) {
                    answer=clues[currentJoke];
                    state=SENTCLUE;//发送完成
                }else {
                    answer="你应该问:\"Who's there?\""+"重新开始:Knock! Knock!";
                }
                break;
            case SENTCLUE: //追问敲门人问答
                if (question.equalsIgnoreCase(clues[currentJoke]+" Who?")) {
                    answer=answers[currentJoke]+" 是否继续 ?(y / n ?)";
                    state=SENTANSWER;
                }else {
                    answer="你应该问:\""+clues[currentJoke]+" Who?\""+"重新开始:Knock! Knock!";
                    state=SENTKNOCKKNOCK;
                }
                break;
            case SENTANSWER: //询问门内人是否继续游戏?
                if (question.equalsIgnoreCase("y")) {
                    answer="Knock! Knock!";
                    if (currentJoke==NUMJOKES-1) {
                        currentJoke=0;
                    }else {
                        currentJoke++;
                    }
                    state=SENTKNOCKKNOCK;
                }else {
                    answer="Game Over! Goodbye!";
                    state=WAITING;
                }
                break;                
        }
        return answer;   
    }//end protocolWorking
}


//自定义协议

服务器设计

package cn.edu.ldu;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;


public class ServerUI extends javax.swing.JFrame {
    private ExecutorService fixedPool; //线程池
    private ServerSocket listenSocket; //侦听套接字
    private Socket toClientSocket; //与客户机对话的套接字
    public static int clientCounts=0; //客户机数量

    /**
     * Creates new form Server
     */
    public ServerUI() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        topPanel = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        txtHostName = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        txtHostPort = new javax.swing.JTextField();
        btnStart = new javax.swing.JButton();
        midPanel = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        txtArea = new javax.swing.JTextArea();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        topPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("启动服务器面板"));

        jLabel1.setText("服务器主机名");

        txtHostName.setText("localhost");

        jLabel2.setText("服务器端口");

        txtHostPort.setText("5000");

        btnStart.setText("启动服务器");
        btnStart.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnStartActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout topPanelLayout = new javax.swing.GroupLayout(topPanel);
        topPanel.setLayout(topPanelLayout);
        topPanelLayout.setHorizontalGroup(
            topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(topPanelLayout.createSequentialGroup()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(txtHostName, javax.swing.GroupLayout.PREFERRED_SIZE, 139, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(44, 44, 44)
                .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 104, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(txtHostPort, javax.swing.GroupLayout.PREFERRED_SIZE, 89, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(39, 39, 39)
                .addComponent(btnStart)
                .addGap(0, 19, Short.MAX_VALUE))
        );
        topPanelLayout.setVerticalGroup(
            topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(topPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(txtHostName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel2)
                    .addComponent(txtHostPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btnStart))
                .addContainerGap(64, Short.MAX_VALUE))
        );

        getContentPane().add(topPanel, java.awt.BorderLayout.PAGE_START);

        midPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("服务器消息面板,服务器扮演“门外人”角色"));
        midPanel.setLayout(new java.awt.BorderLayout());

        txtArea.setColumns(20);
        txtArea.setRows(5);
        jScrollPane2.setViewportView(txtArea);

        midPanel.add(jScrollPane2, java.awt.BorderLayout.CENTER);

        getContentPane().add(midPanel, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>                        

    private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
        try {
            btnStart.setEnabled(false);
            txtHostName.setEnabled(false);
            txtHostPort.setEnabled(false);
             //获取启动参数
            String hostName=txtHostName.getText();
            int hostPort=Integer.parseInt(txtHostPort.getText());
            //构建套接字格式的地址
            SocketAddress serverAddr=new InetSocketAddress(InetAddress.getByName(hostName),hostPort);
            listenSocket=new ServerSocket(); //创建服务器侦听套接字
            listenSocket.bind(serverAddr); //绑定到工作地址
     
            int processors=Runtime.getRuntime().availableProcessors();//CPU数
            fixedPool=Executors.newFixedThreadPool(processors*2);//创建固定大小线程池
            long currentId=Thread.currentThread().getId();//获取编号
           txtArea.append("服务器CPU数:"+processors+"\n 固定线程池大小:"+processors*2+"\n 当前侦听线程ID:"+currentId+"\n 服务器正等待客户机连接...\n");                    
        } catch (IOException ex) { }
        new Thread(new Runnable() {
            public void run() {
              try {            
              while (true) { //处理所有客户机连接
                    toClientSocket=listenSocket.accept();//如果无连接,则阻塞,否则接受连接并创建新的会话套接字
                    clientCounts++;
                    txtArea.append(toClientSocket.getRemoteSocketAddress()+" 客户机编号:"+clientCounts+" 连接到服务器,会话开始...\n");
                    //客户会话线程为SwingWorker类型的后台工作线程
                    Thread clientThread=new ClientThread(toClientSocket,clientCounts); //创建客户线程
                    fixedPool.execute(clientThread); //用线程池调度客户线程运行
                    //clientThread.start(); //这样做就是一客户一线程
                }//end while 
              } catch (IOException ex) {
                    JOptionPane.showMessageDialog(null, ex.getMessage(), "错误提示", JOptionPane.ERROR_MESSAGE);
              }//end try catch            
           }//end run()
        }).start();         
    }                                        

    private void formWindowClosing(java.awt.event.WindowEvent evt) {                                   
        // TODO add your handling code here:
        //关闭套接字和线程池
        try {
            if (toClientSocket!=null) toClientSocket.close();//关闭套接字
            if (listenSocket!=null) listenSocket.close(); 
            if (fixedPool==null)  return;
            fixedPool.shutdown(); //线程池开始关闭
            if (!fixedPool.awaitTermination(60, TimeUnit.SECONDS)) {
                fixedPool.shutdownNow();//强制关闭正执行的线程
                if (!fixedPool.awaitTermination(60, TimeUnit.SECONDS)) {
                    fixedPool.shutdownNow();//强制关闭正执行的线程
                }//超过60秒有线程未关闭执行
            }            
        } catch (IOException | InterruptedException ex) { 
            fixedPool.shutdownNow();//强制关闭正执行的线程
            Thread.currentThread().interrupt();//关闭主线程
        }
    }                                  

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(ServerUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(ServerUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(ServerUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(ServerUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ServerUI().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton btnStart;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JPanel midPanel;
    private javax.swing.JPanel topPanel;
    public static javax.swing.JTextArea txtArea;
    private javax.swing.JTextField txtHostName;
    private javax.swing.JTextField txtHostPort;
    // End of variables declaration                   

    private static class MyThread extends Thread{

        public void run() {
            System.out.println(Thread.currentThread().getName()+"正在运行");
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值