1. 程式人生 > >安卓開發SOCKET程式設計中幾種執行緒阻塞產生的原因與解決辦法

安卓開發SOCKET程式設計中幾種執行緒阻塞產生的原因與解決辦法

在使用socket程式設計中,有幾種情況會使執行緒產生阻塞。
1、解析DNS阻塞
當需要把一個域名解析為IP地址的時候,可用使用以下語句來獲得。使用下面API的時候,如果當前環境沒有網路,或者網路異常,將會使得解析失敗,getByName方法會丟擲異常,但是丟擲異常的時間大約在三四分鐘以後,時間太長。

InetAddress add = InetAddress.getByName(hostname);
String ip=add.getHostAddress();

解決方法(轉載):

package com.liang.client;

import java.net.InetAddress;
import
java.net.UnknownHostException; /** * 自定義解析DNS伺服器類,解決斷網或異常情況下丟擲 UnknownHostException時間太長的問題。 * @author Liang * 用法: * 1、在需要解析的執行緒中建立DNSLookupThread執行緒物件 * DNSLookupThread dnsquery=new DNSLookupThread("liangruimi.vicp.net"); * 2、開啟執行緒 * dnsquery.start(); * 3、設定連線超時時間,這裡等待執行緒執行2s,即如果解析域名時間超過2s,則讀取結果,解析成功,返回的是IP地址,失敗返回的為空 * dnsquery.join(2000); * 4、得到解析結果,如果為NULL,則表示解析失敗 * String ip = dnsquery.getIP(); */
public class DNSLookupThread extends Thread { private InetAddress addr; private String hostname; public DNSLookupThread(String hostname) { this.hostname = hostname; } public void run() { try { InetAddress add = InetAddress.getByName(hostname); set(add); } catch
(UnknownHostException e) { } } private synchronized void set(InetAddress addr) { this.addr = addr; } public synchronized String getIP() { if (null != this.addr) { return addr.getHostAddress(); } return null; } }

2、連結阻塞
當需要與伺服器建立連線的時候,可以用以下方法來建立連線。使用如下方法構造socket物件會引起執行緒的長時間阻塞。因為如果埠無法連線,那麼丟擲異常的時間會很長,整個過程與上訴阻塞類似,大約需要三四分鐘。因此不建議用此方法來建立socket。

socket = new Socket(ipaAddress, 38134);//建立一個連結地址為IPAddress,埠38134為的物件。

解決方法:使用socket的Socket.connect(SocketAddress remoteAddr, int timeout)方法。

socket = new Socket();//建立一個沒有連線的socket物件
SocketAddress saddress = new InetSocketAddress(ip, 38134);//設定連線地址與埠
socket.connect(saddress, 10000);//第二個引數設定連線超時時間,這裡設定為10s。
if (socket.isConnected()) {
        Log.i("liang", "socket已連線");//判斷連線是否成功。
}

3、獲取輸入流阻塞:
當需要獲取socket中輸入流資訊的時候可用使用以下方法,使用InputStreamReader方法將socket中InputStream流轉換為Reader類,並使用Reader類中的readLine方法獲得資訊。但是當呼叫readLine()方法的時候,如果輸入流中沒有任何資料的時候將一直等待,產生執行緒阻塞。

BufferedReader socketin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String socketinMessage = socketin.readLine();

解決方法:
在上述程式碼前設定超時時間

socket.setSoTimeout(50000);//此方法可以設定讀取輸入流超時時間,這裡設定為5s
BufferedReader socketin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String socketinMessage = socketin.readLine();