一、線程創(chuàng)建
1.1 繼承方式
- 創(chuàng)建類湿刽,通過繼承Thread的烁,重寫父類的run()。
- 使用創(chuàng)建對(duì)象诈闺,調(diào)用start()方法渴庆,程序會(huì)單開線程,再自動(dòng)調(diào)用run()方法。
1.2 實(shí)現(xiàn)接口方式
- 創(chuàng)建類襟雷,實(shí)現(xiàn)Runnable接口
- 創(chuàng)建對(duì)象刃滓,創(chuàng)建Thread對(duì)象,并傳入創(chuàng)建的對(duì)象耸弄,Thread對(duì)象調(diào)用start()方法咧虎。
PS:
private void fun(){
//直接建
new Thread(){
@Override
public void run() {
super.run();
}
}.start();
//runnable
new Thread(new Runnable() {
@Override
public void run() {
}
}).start();
}
二、線程使用
- setName函數(shù)计呈,設(shè)置線程的名稱
其他默認(rèn)名字老客,main線程 - Thread.currentThread.getname() 顯示當(dāng)前線程的名稱
2.1 線程異常問題
圖片.png
2.2 線程睡眠
圖片.png
- sleep方法, 參數(shù)是毫秒震叮,必須處理異常
- 在此線程睡眠時(shí),不參與CPU的競(jìng)爭(zhēng)鳍鸵,睡眠結(jié)束后苇瓣,重新加入到CPU的競(jìng)爭(zhēng)。
2.3 線程讓步
圖片.png
- 當(dāng)線程執(zhí)行到此處時(shí)偿乖,此線程暫時(shí)在此處停止击罪,讓出競(jìng)爭(zhēng)到CPU,當(dāng)下次競(jìng)爭(zhēng)到CPU時(shí)贪薪,接著此處繼續(xù)執(zhí)行媳禁。
2.4 線程阻塞
圖片.png
- 遇到j(luò)oin阻塞語句時(shí),暫停當(dāng)前線程画切,直至調(diào)用join的線程執(zhí)行完畢竣稽,其他線程才開始繼續(xù)競(jìng)爭(zhēng)CPU,執(zhí)行程序霍弹。
三毫别、線程優(yōu)先級(jí)
圖片.png
- 優(yōu)先級(jí)不是絕對(duì)的,優(yōu)先級(jí)高典格,只是在競(jìng)爭(zhēng)CPU時(shí)候岛宦,分到的幾率比較高。
- 線程默認(rèn)級(jí)別是5耍缴,數(shù)字越大砾肺,優(yōu)先級(jí)越高。
線程安全問題
package me.gacl.util;
import me.gacl.util.UDPServer;
import me.gacl.domain.ClientInfo;
//采用餓漢式單例類防嗡,類初始化時(shí)变汪,已經(jīng)自行實(shí)例化,線程安全好
public class SocketUtil {
private SocketUtil(){};
private static final SocketUtil socketUtil = new SocketUtil();
//靜態(tài)工廠方法
public static SocketUtil getInstance() {
return socketUtil;
}
static{
//啟動(dòng)socket 服務(wù)器類
UDPServer sharedUDPServer = UDPServer.getInstance();
Thread serverThread = new Thread(sharedUDPServer);
serverThread.start();
}
//添加要轉(zhuǎn)發(fā)的客戶端信息,線程安全問題
public synchronized void addClientInfoToSocketList(String userName, ClientInfo clientInfo){
UDPServer sharedUDPServer = UDPServer.getInstance();
sharedUDPServer.clientInfoList.put(userName, clientInfo);
}
}
package me.gacl.util;
//import java.awt.RenderingHints.Key;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Iterator;
import me.gacl.domain.ClientInfo;
import me.gacl.util.UDPSend;
//import org.apache.tomcat.util.security.PrivilegedSetTccl;
public class UDPServer implements Runnable{
//單例
private UDPServer(){}
private static UDPServer sharedUdpServer = new UDPServer();
public static UDPServer getInstance(){
return sharedUdpServer;
}
//客戶端數(shù)據(jù)
public HashMap<String, ClientInfo> clientInfoList = new HashMap<String, ClientInfo>();
//線程
private static final int INPORT = 5000;
private DatagramSocket serverSocket;
private byte[] recvBuf = new byte[1024];
private DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
@Override
public void run(){
//創(chuàng)建udp服務(wù)器
try {
serverSocket = new DatagramSocket(INPORT);
System.out.println("Server started !");
while (true){
serverSocket.receive(packet);
synchronized (this) {
String recString = new String(packet.getData(), 0, packet.getLength());
//打印接收的信息
String rcvd = "address:"
+ packet.getAddress() + ",port:" + packet.getPort()+",message:"+recString;
System.out.println("From Client:"+rcvd);
//打印clientInfoList
if (recString.equals("761399882")) {
//測(cè)試list
Iterator<String> iterator = clientInfoList.keySet().iterator();
while (iterator.hasNext()) {
String string = (String) iterator.next();
ClientInfo clientInfo = clientInfoList.get(string);
System.out.println("key:"+string+"\t"+"value: "+clientInfo.getIpString()+"\t"+clientInfo.getPortInt());
}
continue;
}
//處理接受的數(shù)據(jù)
if (clientInfoList.containsKey(recString)) {
ClientInfo clientInfo = clientInfoList.get(recString);
UDPSend udpSend = new UDPSend(recString, clientInfo, serverSocket);
udpSend.start();
}
}
//對(duì)接收到的數(shù)據(jù)處理轉(zhuǎn)發(fā)
//測(cè)試list
/* Iterator<String> iterator = clientInfoList.keySet().iterator();
while (iterator.hasNext()) {
String string = (String) iterator.next();
ClientInfo clientInfo = clientInfoList.get(string);
System.out.println("key:"+string+"\t"+"value: "+clientInfo.getIpString()+"\t"+clientInfo.getPortInt());
}*/
}
} catch (SocketException e) {
System.err.println("Can't open socket");
//System.exit(1);
} catch (Exception e) {
System.err.println("Communication error");
e.printStackTrace();
} finally{
serverSocket.close();
}
}
}
package me.gacl.util;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import me.gacl.domain.ClientInfo;
public class UDPSend extends Thread{
private String sendStr;
private ClientInfo clientInfo;
private DatagramSocket serverSocket;
public UDPSend(String sendStr, ClientInfo clientInfo,
DatagramSocket serverSocket) {
super();
this.sendStr = sendStr;
this.clientInfo = clientInfo;
this.serverSocket = serverSocket;
}
public void run() {
synchronized (this) {
System.out.println("UDPSend:"+clientInfo.getIpString()+"\t"+clientInfo.getPortInt());
try {
InetAddress address = InetAddress.getByName(clientInfo.getIpString());
int port = clientInfo.getPortInt();
byte[] sendBuf = sendStr.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, address, port);
serverSocket.send(sendPacket);
//線程安全測(cè)試
//sleep(9000);
//System.out.println("serverSocket.send"+sendStr);
} catch (Exception e) {
System.err.println("Communication error");
e.printStackTrace();
}
}
}
}