欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java Socket一對(duì)多通信實(shí)現(xiàn)之并發(fā)處理方式

 更新時(shí)間:2023年08月28日 14:12:50   作者:從北碼到南  
這篇文章主要介紹了Java Socket一對(duì)多通信實(shí)現(xiàn)之并發(fā)處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

效果圖

場(chǎng)景描述

多臺(tái)傳感器連接至服務(wù)端時(shí),保存每臺(tái)傳感器最初的登錄順序和 socket 信息,然后根據(jù)登錄順序進(jìn)行頁(yè)面排序,當(dāng)設(shè)備掉線或者主動(dòng)斷開(kāi)時(shí)移除 socket 連接信息

代碼設(shè)計(jì)

1. 創(chuàng)建一個(gè)GlobalCommonUtil的工具類(lèi)

存放全局靜態(tài)集合 

    //存放設(shè)備連接信息 eg: mac 登錄狀態(tài) 初始登錄順序等
    public static List<TcpObject> list = new LinkedList<TcpObject>();
    //存放設(shè)備初始登錄順序(累計(jì)排序)
    public static List<FileObject> fileInfo = new LinkedList<FileObject>();
    //存放 socket 連接對(duì)象,mac 為key 此處為線程安全的 map 集合
    public static Map<String,Socket> map = new ConcurrentHashMap<String, Socket>();

2.創(chuàng)建線程通信類(lèi)SocketThread

初始化 ServerSocket 和 Socket 對(duì)象

public class SocketThread  extends Thread{
	ServerSocket server;
	Socket client;
    public SocketThread(Socket socket){  
        this.client = socket;  
    }  
    @Override
    public void run() {
	try {
		reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
        // 讀取reader中的信息...
	  } catch (Exception e) {
		//捕獲socket強(qiáng)制斷開(kāi)異常信息,移除socket
    }	
 }
}

3.創(chuàng)建線程啟動(dòng)類(lèi)

public class TcpServer {
    public static void main(String[] args) {
        start();
    }
	 public void start() {
	        try {
	            //記錄鏈接過(guò)的客戶端個(gè)數(shù)
	            //1、創(chuàng)建一個(gè)服務(wù)器端Socket,即ServerSocket,綁定指定的端口,進(jìn)行監(jiān)聽(tīng)
	            ServerSocket serverSocket = new ServerSocket(9000);
	            log.info("服務(wù)器即將啟動(dòng),等待客戶端連接");
	            //2、循環(huán)監(jiān)聽(tīng)等待客戶端的連接
	            while(true){
	                //調(diào)用accept方法 等待客戶端的連接
	                Socket socket = serverSocket.accept();
	                if(!GlobalCommonUtil.isStart) {
	                	 //創(chuàng)建一個(gè)新的線程
		                SocketThread serverThread = new SocketThread(socket);
		                //啟動(dòng)線程
		                serverThread.start();
		                GlobalCommonUtil.count++;
		                log.info("連接過(guò)的客戶端數(shù)量為:" + GlobalCommonUtil.count);
	            	}
	            }
	        } catch (IOException e) {
	            e.printStackTrace();
	        }
	}
}

測(cè)試環(huán)境中,由于真實(shí)場(chǎng)景和真實(shí)設(shè)備均沒(méi)有見(jiàn)過(guò),也無(wú)法考慮設(shè)備車(chē)間是怎么回事,只能老套路。

用tcp連接工具模擬登錄,登錄,數(shù)據(jù)收發(fā)時(shí)均無(wú)問(wèn)題,代碼運(yùn)行良好,開(kāi)發(fā)測(cè)試都 ok ,然后交付了,再然后>跪了< 。。。

問(wèn)題一:

全局靜態(tài)資源的并發(fā)操作引起的線程不安全:

 for(TcpObject tcpObject : GlobalCommonUtil.list) {
 if(tcpObject.getMac().equals(mac)) {
	GlobalCommonUtil.list.remove(tcpObject);
	break;
   }
}
GlobalCommonUtil.count--;
log.info("遠(yuǎn)程客戶端已關(guān)閉連接!");

但客戶端異常斷開(kāi)時(shí),GlobalCommonUtil.list 的 remove  其他線程的讀取很容易就會(huì) java.lang.NullPointerException,多線程之間共享變量,從而導(dǎo)致的線程不安全問(wèn)題,如果我們讓每個(gè)線程依次去讀寫(xiě)這個(gè)變量,這樣應(yīng)該可以避免不安全問(wèn)題了

加 synchronized 鎖

分類(lèi)具體分類(lèi)被鎖的對(duì)象偽代碼
方法實(shí)例方法類(lèi)的實(shí)例對(duì)象

// 實(shí)例方法 鎖住的是該類(lèi)的實(shí)例對(duì)象

public synchronized void method(){

  // action ...

}

靜態(tài)方法類(lèi)對(duì)象

// 靜態(tài)方法,鎖住的是類(lèi)對(duì)象

public static synchronized void method(){

  // action ...

}

代碼塊實(shí)例對(duì)象類(lèi)的實(shí)例對(duì)象

// 同步代碼塊,鎖住的是該類(lèi)的實(shí)例對(duì)象

synchronized (this){

   // action ...

}

class對(duì)象類(lèi)對(duì)象

// 同步代碼塊,鎖住的是該類(lèi)的類(lèi)對(duì)象

synchronized (Dermo.class){

   // action ...

}

任意實(shí)例對(duì)象Object實(shí)例對(duì)象

// 同步代碼塊,鎖住的是配置的實(shí)例對(duì)象

//String 對(duì)象作為鎖

String lock = “”

synchronized (lock){

   // action ...

}

注:

如果鎖的是類(lèi)的實(shí)例對(duì)象的話,每次 new 的操作都是創(chuàng)建一個(gè)新的對(duì)象,就出現(xiàn) synchronized 鎖不住對(duì)象的現(xiàn)象,如果鎖的是類(lèi)對(duì)象的話,無(wú)論new多少個(gè)實(shí)例對(duì)象,他們?nèi)匀粫?huì)被鎖住,即可保證線程之間的同步關(guān)系,synchronized 底層原理是使用了對(duì)象持有的監(jiān)視器(monitor),但是同步代碼塊和同步方法的原理存在一點(diǎn)差異:

  • 同步代碼塊使用的 monitorenter 和 monitorexit 指令實(shí)現(xiàn)的
  • 同步方法是由方法調(diào)用指令讀取運(yùn)行時(shí)常量池中方法的 ACC_SYNCHRONIZRED 標(biāo)識(shí)隱式實(shí)現(xiàn),實(shí)際上還是調(diào)用了   monitorenter 和 monitorexit 指令     

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論