java网络编程:5,多线程

关于java多线程说明;

start()方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态,什么时候运行是由操作系统决定的。针对Thread类,从程序1运行的结果可以发现,多线程程序是乱序执行(即先执行完线程a全部操作再进行线程B操作)。因此,只有乱序执行的代码才有必要设计为多线程。假如我们对线程进行sleep操作,我们可以发现线程Asleep时线程B会进行操作,因此Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留出一定时间给其他线程执行的机会。了解这一点,我们可以进行以下实验

 

1,编写一个类,类名为SubThread,继承Thread。该类中:

  1. 定义一个构造方法,用于设置线程名字;
  2. 以及定义一个run()方法,在方法中写有一个for循环,循环一共进行5次,循环体中先在控制台打印显示该线程循环了第几次,然后随机休眠小于一秒的时间;循环结束后显示线程结束信息:线程名+finished。
  3. 编写一个主应用程序,并在其中创建SubThread类的三个线程对象t1,t2,t3,线程名字分别设置为First,Second,Third,并启动这三个线程。

代码如下:

package network_chap05;

public class SubThread extends Thread {
	public String threadName;
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new SubThread("First").start();
		new SubThread("Second").start();
		new SubThread("Third").start();
		
		
	}
	
	public SubThread_Test(String threadName){
        this.threadName = threadName;
    }
	
	

	public void run() {
		for(int i=1;i<=5;i++){
			System.out.print("A线程循环了第"+i+"次\n");
			try {
				sleep(new java.util.Random().nextInt(1000) + 1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}	
		System.out.print("A线程"+"finished\n");
	}


}

Synchronized实现同步运算

分析:

在 Java 中,关键字 synchronized可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块。

一进程的多个线程共享同一片存储空间,为了避免访问冲突的情况JAVA提供了一种同步机制的办法,用synchronized关键字来修饰共享的代码块,确保在某个时刻只有一个线程允许执行特定的代码块。

一个线程在访问被synchronized修饰的数据时,会将其“上锁”,阻止其他线程访问。只有当前线程访问完这部分数据后释放锁标志,其他线程才可以访问。

注意无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或方法当作锁。

扫描二维码关注公众号,回复: 5902723 查看本文章

synchronized关键字最主要有以下3种应用方式,

修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁

修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁

修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁

举例如下:

未使用Synchronized时:

class MySyncThreadApp

package network_chap05;

public class MySyncThreadApp {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		MyCalculate cal = new MyCalculate();
		
		MySyncThread a = new MySyncThread("A",cal);
		MySyncThread b = new MySyncThread("B",cal);
		MySyncThread c = new MySyncThread("C",cal);
		MySyncThread d = new MySyncThread("D",cal);
		
		a.start();
		b.start();
		c.start();
		d.start();

	}

}

class  MyCalculate

package network_chap05;

public class  MyCalculate {
	private  int count =0;
	
	public   synchronized void setCount(){
		count++;
	}
	public  int getCount(){
		return count;
	}
}

class MySyncThread

package network_chap05;

public class MySyncThread extends Thread {
	public MyCalculate cal;
	public String name;
	
	public MySyncThread (String name, MyCalculate cal) {
		super(name);
		this.cal = cal;
	}
	
	public void run (){
		
		for(int i=0;i<100000;i++){
			cal.setCount();
		}
		System.out.println(getName() + " end, the count is: " + cal.getCount());
		
	}
}

通过运行我们发现:

很明显,我们发现,我们开启4个线程,每个线程都调用同一个函数cal进行计数,但最后一个结束的线程输出结果却没有达到40000,原因便是:如下图,当第一个线程运行cal到5,此时运行第6次,但是当运行到第一句代码时,第一个线程的时间片用完了,此时cal=5,这时候时间片轮到第二个线程,假如第二个线程用完时间片时把把代码全部运行完,假设此时从cal=5到了600,此时时间片假如又轮到第一个线程,而此时第一个线程运行第二句代码,因此cal依旧还是5,加1后cal=6,输出cal后,cal从600变成了6,所以这样导致我们达不到多线程的效果,而Synchronized就是将程序进行上锁”,回到刚刚的情况,当运行到第一句代码时,第一个线程的时间片用完了,此时cal=5,由于使用Synchronized导致程序上锁”,因为后面3个线程拿不到时间片,进入堵塞状态,只有当再次轮到第一个线程拿到时间片进行运行时,才能“解锁”。

实现如下:

修改class  MyCalculate

package network_chap05;

public class  MyCalculate {
	private  int count =0;
	
	public synchronized  void setCount(){
		count++;
	}
	public  int getCount(){
		return count;
	}
}

运行结果如下:

将前面的MyServer,MyClient,ClientThread改写为多线程格式

实现思路:

MyClient:

1,原先的MyServer,使用线程ClientThread进行接收,没有发的线程,为了使服务器能只有与客户机进行交互,因此需要再建立一个线程,用于返回抓取text框内需要返回给客户机的信息。

2,该线程再抓取完信息之后启动。

MyClient:

Client进行信息收发的步骤改写为两个线程,一个线程进行发,一个线程进行收。

实现代码如下:

class ClientThread

package cn.edu.sise;

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.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JTextArea;

/**
 *
 * @author World
 */
public class ClientThread extends Thread {
    private Socket toClientSocket=null;//会话套接字
    private BufferedReader in; //网络输入流
    private PrintWriter out; //网络输出流
    private int clientCounts=0;//在线客户机总数
//    public ClientThread(Socket toClientSocket,int clientCounts) { //构造函数
//        this.toClientSocket=toClientSocket;
//        this.clientCounts=clientCounts;
//    }   
    private JTextArea jta;
    public ClientThread(Socket toClientSocket,int clientCounts, JTextArea jta) { //构造函数
        this.toClientSocket=toClientSocket;
        this.clientCounts=clientCounts;
        this.jta = jta;
    }   
    @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);
            //5. 根据服务器协议,在网络流上进行读写操作
            String recvStr;
            while ((recvStr=in.readLine())!=null){ //只要客户机不关闭,则反复等待和接收客户机消息
               Date date=new Date();
               DateFormat format=new SimpleDateFormat("yyyy-mm-dd hh:mm:ss");
               String time=format.format(date);
               jta.append(toClientSocket.getRemoteSocketAddress()+ " 客户机编号: "+clientCounts+" 消息:"+recvStr+" :"+time+"\n"); //解析并显示收到的消息
               //按照echo协议原封不动回送消息
               out.println(toClientSocket.getLocalSocketAddress()+ " 客户机编号: "+clientCounts+" Echo消息:"+recvStr+" : "+time);
            }//end while   
            MyServer.clientCounts--; //客户机总数减1
           
        }catch (IOException ex) {}finally{
            try {
                //远程客户机断开连接,线程释放资源
                if (in!=null) in.close();
                if (out!=null) out.close();
                if (toClientSocket!=null) toClientSocket.close();  			
			} catch (Exception e) {
				// TODO: handle exception
			}    	

        }
    } //end run
} //end class

class MyClient

package cn.edu.sise;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.ScrollPane;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;

import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class MyClient {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JFrame frame = new JFrame("Client: 1707");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		frame.getContentPane().add(new MyPanel());
		frame.setPreferredSize(new Dimension(800, 300));
		frame.pack();
		frame.setVisible(true);
	}

}

class MyPanel extends JPanel{
	JTextField tf;
	JTextArea ta;
	JTextField tfAddr;
	JTextField tfPort;
	
    BufferedReader in = null;
    BufferedWriter out = null;
    
	public MyPanel(){
		
		this.setLayout(new BorderLayout());
		
		JPanel pcon = new JPanel();	
		JLabel lb1 = new JLabel();
		lb1.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
		lb1.setText("Server Host Name:");
		tfAddr = new JTextField(25);
		JLabel lb2 = new JLabel();
		lb2.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
		lb2.setText("Port:");
		tfPort = new JTextField(5);
		JButton btnConnect = new JButton("Connect");
		btnConnect.addActionListener(new MyConnectListerner());
		pcon.add(lb1);
		pcon.add(tfAddr);
		pcon.add(lb2);
		pcon.add(tfPort);
		pcon.add(btnConnect);
		pcon.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Connection Border", 
				javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, 
				javax.swing.border.TitledBorder.DEFAULT_POSITION, 
				new java.awt.Font("宋体", 1, 14))); // NOI18N
		this.add(pcon, BorderLayout.NORTH);

		
		JPanel pcom = new JPanel();	

		JLabel lb3 = new JLabel();
		lb3.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
		lb3.setText("Message:");
		pcom.add(lb3);
		tf = new JTextField(25);
		pcom.add(tf );
		JButton btn = new JButton("Send");
		btn.addActionListener(new MySendListerner());
		pcom.add(btn);

		pcom.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Communication Border", 
        											javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, 
        											javax.swing.border.TitledBorder.DEFAULT_POSITION, 
        											new java.awt.Font("宋体", 1, 14))); // NOI18N

		this.add(pcom, BorderLayout.SOUTH);
		
		JPanel pinfo = new JPanel();
        pinfo.setLayout(new java.awt.BorderLayout());
        pinfo.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Information Border",
                javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
                javax.swing.border.TitledBorder.DEFAULT_POSITION,
                new java.awt.Font("宋体", 1, 14))); // NOI18N

        JScrollPane sp1 = new JScrollPane();
        sp1.setPreferredSize(new java.awt.Dimension(8, 250));
        ta = new JTextArea(5, 10);
        ta.setEditable(false);
        sp1.setViewportView(ta);
        pinfo.add(sp1, BorderLayout.CENTER);
        this.add(pinfo, BorderLayout.CENTER);


	}
	
	class MyConnectListerner implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			String addr = tfAddr.getText();
			if(addr.trim().equals("")) addr = "localhost";
			int port = Integer.parseInt(tfPort.getText());
			System.out.println(addr + ":" + port);
			
			try{
				Socket  s = new Socket();
			    SocketAddress remoteAddr=new InetSocketAddress(addr,port); 
			    s.connect(remoteAddr);
			    ta.append("Connect to server: " + addr + ":" + port + "\n");
	            in = new BufferedReader(
	                    new InputStreamReader(s.getInputStream(),"UTF-8"));           
	            out = new BufferedWriter(
	                    new OutputStreamWriter(s.getOutputStream(),"UTF-8"));
	            new Thread(new MessageReceiver()).start();
	        } catch (IOException ex) {
	            System.out.println("异常信息:"+ex.getMessage());
	        }
		}
	}
	
	class MySendListerner implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent e) {
			new Thread(new MessageSender()).start();
		}
		
	}
	class MessageSender implements Runnable{
		@Override
        public void run() {
            try {
                String sendStr = tf.getText();
                tf.setText("");
                out.write(sendStr);  //向服务器发送字符串
                out.newLine();
                out.flush();
                System.out.println("3.1向服务器发送字符串成功!" + sendStr);
                ta.append("To server: " + sendStr + "\n");
            } catch (IOException ex) {
                System.out.println("异常信息:" + ex.getMessage());
            }
        }
		
	}
	class MessageReceiver implements Runnable{
		@Override
        public void run() {
			String receiver;
            try {
            	while ((receiver = in.readLine())!=null){
                    ta.append("From Server: " + receiver + "\n");
                }
            } catch (IOException ex) {
                System.out.println("异常信息:" + ex.getMessage());
            }
        }
		
	}
	
	
}

class MyServer

package cn.edu.sise;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import cn.edu.sise.MyPanel.MySendListerner;

/**
 * Echo服务器:根据Echo协议,接收来自客户机消息,并立即回送。
 
 */
public class MyServer extends javax.swing.JFrame {
    private ServerSocket listenSocket=null; //侦听套接字
    private Socket toClientSocket=null; //与客户机对话的套接字
    public static int clientCounts=0; //客户数量编号
    
    /**
     * Creates new form EchoServer
     */
    public MyServer() {
        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">//GEN-BEGIN:initComponents
    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();
        jScrollPane1 = new javax.swing.JScrollPane();
        txtArea = new javax.swing.JTextArea();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("My Server: 1707");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        topPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Server Info Border", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("宋体", 1, 18))); // NOI18N

        jLabel1.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
        jLabel1.setText("Host Name:");

        txtHostName.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
        txtHostName.setText("localhost");

        jLabel2.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
        jLabel2.setText("Port:");

        txtHostPort.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
        txtHostPort.setText("7");

        btnStart.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
        btnStart.setText("Start");
        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()
                .addContainerGap()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(txtHostName, javax.swing.GroupLayout.DEFAULT_SIZE, 131, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(txtHostPort, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(btnStart)
                .addContainerGap())
        );
        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(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

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

        midPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Information Border", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("宋体", 1, 18))); // NOI18N
        midPanel.setLayout(new java.awt.BorderLayout());

        txtArea.setEditable(false);
        txtArea.setBackground(new java.awt.Color(204, 255, 255));
        txtArea.setColumns(20);
        txtArea.setFont(new java.awt.Font("宋体", 1, 16)); // NOI18N
        txtArea.setRows(5);
        jScrollPane1.setViewportView(txtArea);

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

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

        pack();
    }// </editor-fold>//GEN-END:initComponents
    //启动服务器
    private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStartActionPerformed
    
        try {
            btnStart.setEnabled(false); //禁用按钮,避免重复启动
            String hostName=txtHostName.getText();//主机名
            int hostPort=Integer.parseInt(txtHostPort.getText());//端口
            //构建服务器的SocketAddress格式地址
            SocketAddress serverAddr=new InetSocketAddress(InetAddress.getByName(hostName),hostPort);
            listenSocket=new ServerSocket(); //创建侦听套接字
            listenSocket.bind(serverAddr);  //绑定到工作地址 
            txtArea.append("服务器开始等待客户机连接...\n");             
        } catch (IOException ex) {    }
        
        //创建一个匿名线程,用于侦听和接受客户机连接,并创建响应客户机的会话线程
        new Thread(new Runnable() {  
            @Override
            public void run() {
                try {
                    while (true) { //处理客户机连接
                        toClientSocket=listenSocket.accept();//侦听并接受客户机连接
                        clientCounts++;//客户机数量加1                   
                        txtArea.append(toClientSocket.getRemoteSocketAddress()+ " 客户机编号: "+clientCounts+ " 会话开始...\n");
                                            
                		JFrame frame = new JFrame("From Client: "+ toClientSocket.getRemoteSocketAddress());
                		
                		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                		
                		MyPanel panel = new MyPanel();
                		frame.getContentPane().add(panel);
                		frame.setPreferredSize(new Dimension(600, 300));
                		frame.pack();
                		frame.setVisible(true);
                                      
                        //创建客户线程clientThread,实现一客户一线程
                       Thread clientThread=new ClientThread(toClientSocket,clientCounts,panel.taClient); 
                        clientThread.start(); //启动任务线程
                                           
                    } //end while                                     
                } catch (IOException ex) {
                    JOptionPane.showMessageDialog(null, ex.getMessage(), "错误提示", JOptionPane.ERROR_MESSAGE);
                }           
            }//end run()
            class MyPanel extends JPanel{          	
            	
            	public javax.swing.JTextArea taClient;
				JTextField tf;
				
            	
            	public MyPanel(){
            		
            		this.setLayout(new BorderLayout());          		
            		
            		JPanel pinfo = new JPanel();
            		JPanel border = new JPanel();
            		
            		pinfo.setLayout(new java.awt.BorderLayout());
            		pinfo.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Information Border", 
            				javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, 
            				javax.swing.border.TitledBorder.DEFAULT_POSITION, 
            				new java.awt.Font("宋体", 1, 14))); // NOI18N

                    JScrollPane sp1 = new  JScrollPane();
                    sp1.setPreferredSize(new java.awt.Dimension(8, 250));
                    
                    taClient = new JTextArea(5,10);
                   
                    taClient.setEditable(false);
            		sp1.setViewportView(taClient);
            		pinfo.add(sp1,BorderLayout.CENTER);
            		this.add(pinfo, BorderLayout.CENTER);
            		
            		 tf=new JTextField(40);
                     JButton tfbtn_send = new JButton("Send");
                     tfbtn_send.addActionListener(new MySendListerner());
                     border.add(tfbtn_send);

                     border.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Communication Border", 
                     											javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, 
                     											javax.swing.border.TitledBorder.DEFAULT_POSITION, 
                     											new java.awt.Font("宋体", 1, 14))); // NOI18N
                     border.add(tf);
                     border.add(tfbtn_send);
                     this.add(border, BorderLayout.SOUTH);
 
            		new Thread(new MessageRecver()).start();
            	}
            	class MySendListerner implements ActionListener{

            		@Override
            		public void actionPerformed(ActionEvent e) {
            			
            			// TODO Auto-generated method stub
            			new Thread(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(toClientSocket.getOutputStream()));
                                    out.write(tf.getText());
                                    out.newLine();
                                    out.flush();
                                    taClient.append("To client: " + tf.getText());
                                    tf.setText("");
                                } catch (IOException e1) {
                                    e1.printStackTrace();
                                }
                            }
                        }).start();
            			
            		}
            		
            	}
            	class MessageRecver implements Runnable{
                    @Override
                    public void run() {
                        try {
                            BufferedReader in = new BufferedReader(new InputStreamReader(toClientSocket.getInputStream()));
                            String recvMessage;
                            while ((recvMessage = in.readLine())!=null){
                                taClient.append("From client: " + recvMessage + "\n");
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        };
                    }
                }
            }
            
        }).start();
    }//GEN-LAST:event_btnStartActionPerformed
    //关闭服务器之前
    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        //关闭服务器之前释放套接字
        if (listenSocket!=null) listenSocket=null;
        if (toClientSocket!=null) toClientSocket=null;
    }//GEN-LAST:event_formWindowClosing

    /**
     * @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(MyServer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MyServer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MyServer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MyServer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>
        //</editor-fold>
        //</editor-fold>
        //</editor-fold>

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

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnStart;
    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;
    public static javax.swing.JTextArea txtArea;
    private javax.swing.JTextField txtHostName;
    private javax.swing.JTextField txtHostPort;
    // End of variables declaration//GEN-END:variables
    
    
}

猜你喜欢

转载自blog.csdn.net/qq_41686130/article/details/83628748