如题所述
æ们ç¥éSpringéè¿åç§DAO模æ¿ç±»éä½äºå¼åè
使ç¨åç§æ°æ®æä¹
ææ¯çé¾åº¦ãè¿äºæ¨¡æ¿ç±»é½æ¯çº¿ç¨å®å
¨çï¼ä¹å°±æ¯è¯´ï¼å¤ä¸ªDAOå¯ä»¥å¤ç¨åä¸ä¸ªæ¨¡æ¿å®ä¾èä¸ä¼åçå²çªã
æ们使ç¨æ¨¡æ¿ç±»è®¿é®åºå±æ°æ®ï¼æ ¹æ®æä¹ åææ¯çä¸åï¼æ¨¡æ¿ç±»éè¦ç»å®æ°æ®è¿æ¥æä¼è¯çèµæºãä½è¿äºèµæºæ¬èº«æ¯é线ç¨å®å ¨çï¼ä¹å°±æ¯è¯´å®ä»¬ä¸è½å¨åä¸æ¶å»è¢«å¤ä¸ªçº¿ç¨å ±äº«ã
è½ç¶æ¨¡æ¿ç±»éè¿èµæºæ± è·åæ°æ®è¿æ¥æä¼è¯ï¼ä½èµæºæ± æ¬èº«è§£å³çæ¯æ°æ®è¿æ¥æä¼è¯çç¼åé®é¢ï¼å¹¶éæ°æ®è¿æ¥æä¼è¯ç线ç¨å®å ¨é®é¢ã
æç §ä¼ ç»ç»éªï¼å¦ææ个对象æ¯é线ç¨å®å ¨çï¼å¨å¤çº¿ç¨ç¯å¢ä¸ï¼å¯¹å¯¹è±¡ç访é®å¿ é¡»éç¨synchronizedè¿è¡çº¿ç¨åæ¥ãä½SpringçDAO模æ¿ç±»å¹¶æªéç¨çº¿ç¨åæ¥æºå¶ï¼å 为线ç¨åæ¥éå¶äºå¹¶å访é®ï¼ä¼å¸¦æ¥å¾å¤§çæ§è½æ失ã
æ¤å¤ï¼éè¿ä»£ç åæ¥è§£å³æ§è½å®å ¨é®é¢æææ§å¾å¤§ï¼å¯è½ä¼å¢å¼ºå¥½å åçå®ç°é¾åº¦ãé£æ¨¡æ¿ç±»ç©¶ç«ä»°ä¸ä½ç§éæ³ç¥åï¼å¯ä»¥å¨æ éåæ¥çæ åµä¸å°±å解线ç¨å®å ¨çé¾é¢å¢ï¼çæ¡å°±æ¯ThreadLocalï¼
ThreadLocalå¨Springä¸åæ¥çéè¦çä½ç¨ï¼å¨ç®¡çrequestä½ç¨åçBeanãäºå¡ç®¡çãä»»å¡è°åº¦ãAOPç模åé½åºç°äºå®ä»¬ç身影ï¼èµ·ç举足轻éçä½ç¨ãè¦æ³äºè§£Springäºå¡ç®¡ççåºå±ææ¯ï¼ThreadLocalæ¯å¿ é¡»æ»å çå±±å¤´å ¡åã
ThreadLocalæ¯ä»ä¹
æ©å¨JDK1.2ççæ¬ä¸å°±æä¾java.lang.ThreadLocalï¼ThreadLocal为解å³å¤çº¿ç¨ç¨åºç并åé®é¢æä¾äºä¸ç§æ°çæè·¯ã使ç¨è¿ä¸ªå·¥å ·ç±»å¯ä»¥å¾ç®æ´å°ç¼ååºä¼ç¾çå¤çº¿ç¨ç¨åºã
ThreadLocalå¾å®¹æ让人ææçä¹ï¼æ³å½ç¶å°è®¤ä¸ºæ¯ä¸ä¸ªâæ¬å°çº¿ç¨âãå ¶å®ï¼ThreadLocal并ä¸æ¯ä¸ä¸ªThreadï¼èæ¯Threadçå±é¨åéï¼ä¹è®¸æå®å½å为ThreadLocalVariableæ´å®¹æ让人ç解ä¸äºã
å½ä½¿ç¨ThreadLocalç»´æ¤åéæ¶ï¼ThreadLocal为æ¯ä¸ªä½¿ç¨è¯¥åéç线ç¨æä¾ç¬ç«çåéå¯æ¬ï¼æ以æ¯ä¸ä¸ªçº¿ç¨é½å¯ä»¥ç¬ç«å°æ¹åèªå·±çå¯æ¬ï¼èä¸ä¼å½±åå ¶å®çº¿ç¨æ对åºçå¯æ¬ã
ä»çº¿ç¨çè§åº¦çï¼ç®æ åé就象æ¯çº¿ç¨çæ¬å°åéï¼è¿ä¹æ¯ç±»åä¸âLocalâæè¦è¡¨è¾¾çææã
线ç¨å±é¨åé并ä¸æ¯Javaçæ°åæï¼å¾å¤è¯è¨ï¼å¦IBM IBM XLFORTRANï¼å¨è¯æ³å±é¢å°±æä¾çº¿ç¨å±é¨åéãå¨Javaä¸æ²¡ææä¾å¨è¯è¨çº§æ¯æï¼èæ¯åç¸å°éè¿ThreadLocalçç±»æä¾æ¯æã
æ以ï¼å¨Javaä¸ç¼å线ç¨å±é¨åéç代ç ç¸å¯¹æ¥è¯´è¦ç¬¨æä¸äºï¼å æ¤é æ线ç¨å±é¨åé没æå¨Javaå¼åè ä¸å¾å°å¾å¥½çæ®åã
ThreadLocalçæ¥å£æ¹æ³
ThreadLocalç±»æ¥å£å¾ç®åï¼åªæ4个æ¹æ³ï¼æ们å æ¥äºè§£ä¸ä¸ï¼
void set(Object value)
设置å½å线ç¨ç线ç¨å±é¨åéçå¼ã
public Object get()
该æ¹æ³è¿åå½å线ç¨æ对åºç线ç¨å±é¨åéã
public void remove()
å°å½å线ç¨å±é¨åéçå¼å é¤ï¼ç®çæ¯ä¸ºäºåå°å åçå ç¨ï¼è¯¥æ¹æ³æ¯JDK5.0æ°å¢çæ¹æ³ãéè¦æåºçæ¯ï¼å½çº¿ç¨ç»æåï¼å¯¹åºè¯¥çº¿ç¨çå±é¨åéå°èªå¨è¢«åå¾åæ¶ï¼æ以æ¾å¼è°ç¨è¯¥æ¹æ³æ¸ é¤çº¿ç¨çå±é¨åé并ä¸æ¯å¿ é¡»çæä½ï¼ä½å®å¯ä»¥å å¿«å ååæ¶çé度ã
protected Object initialValue()
è¿å该线ç¨å±é¨åéçåå§å¼ï¼è¯¥æ¹æ³æ¯ä¸ä¸ªprotectedçæ¹æ³ï¼æ¾ç¶æ¯ä¸ºäºè®©åç±»è¦çè设计çãè¿ä¸ªæ¹æ³æ¯ä¸ä¸ªå»¶è¿è°ç¨æ¹æ³ï¼å¨çº¿ç¨ç¬¬1次è°ç¨get()æset(Object)æ¶ææ§è¡ï¼å¹¶ä¸ä» æ§è¡1次ãThreadLocalä¸ç缺çå®ç°ç´æ¥è¿åä¸ä¸ªnullã
å¼å¾ä¸æçæ¯ï¼å¨JDK5.0ä¸ï¼ThreadLocalå·²ç»æ¯ææ³åï¼è¯¥ç±»çç±»åå·²ç»å为ThreadLocal<T>ãAPIæ¹æ³ä¹ç¸åºè¿è¡äºè°æ´ï¼æ°çæ¬çAPIæ¹æ³åå«æ¯voidset(T value)ãT get()以åT initialValue()ã
ThreadLocalæ¯å¦ä½åå°ä¸ºæ¯ä¸ä¸ªçº¿ç¨ç»´æ¤åéçå¯æ¬çå¢ï¼å ¶å®å®ç°çæè·¯å¾ç®åï¼å¨ThreadLocalç±»ä¸æä¸ä¸ªMapï¼ç¨äºåå¨æ¯ä¸ä¸ªçº¿ç¨çåéå¯æ¬ï¼Mapä¸å ç´ çé®ä¸ºçº¿ç¨å¯¹è±¡ï¼èå¼å¯¹åºçº¿ç¨çåéå¯æ¬ãæ们èªå·±å°±å¯ä»¥æä¾ä¸ä¸ªç®åçå®ç°çæ¬ï¼
// 代ç æ¸ å1 SimpleThreadLocal
class SimpleThreadLocal {
private MapvalueMap = Collections.synchronizedMap(new HashMap());
public voidset(Object newValue) {
valueMap.put(Thread.currentThread(), newValue);//â é®ä¸ºçº¿ç¨å¯¹è±¡ï¼å¼ä¸ºæ¬çº¿ç¨çåéå¯æ¬
}
publicObject get() {
Thread currentThread = Thread.currentThread();
Object o = valueMap.get(currentThread);// â¡è¿åæ¬çº¿ç¨å¯¹åºçåé
if (o == null &&!valueMap.containsKey(currentThread)) {// â¢å¦æå¨Mapä¸ä¸åå¨ï¼æ¾å°Map
// ä¸ä¿åèµ·æ¥ã
o = initialValue();
valueMap.put(currentThread, o);
}
return o;
}
public voidremove() {
valueMap.remove(Thread.currentThread());
}
publicObject initialValue() {
return null;
}
}
è½ç¶ä»£ç æ¸ å9?3è¿ä¸ªThreadLocalå®ç°çæ¬æ¾å¾æ¯è¾å¹¼ç¨ï¼ä½å®åJDKææä¾çThreadLocalç±»å¨å®ç°æè·¯ä¸æ¯ç¸è¿çã
ä¸ä¸ªTheadLocalå®ä¾
ä¸é¢ï¼æ们éè¿ä¸ä¸ªå ·ä½çå®ä¾äºè§£ä¸ä¸ThreadLocalçå ·ä½ä½¿ç¨æ¹æ³
package threadLocalDemo;
public class SequenceNumber {
//â éè¿å¿åå é¨ç±»è¦çThreadLocalçinitialValue()æ¹æ³ï¼æå®åå§å¼
privatestatic ThreadLocal<Integer> seqNum =new ThreadLocal<Integer>() {
public Integer initialValue() {
return 0;
}
};
//â¡è·åä¸ä¸ä¸ªåºåå¼
public intgetNextNum() {
seqNum.set(seqNum.get() + 1);
return seqNum.get();
}
publicstatic void main(String[] args)
{
SequenceNumber sn = new SequenceNumber();
// ⢠3个线ç¨å ±äº«snï¼åèªäº§çåºåå·
TestClient t1 = new TestClient(sn);
TestClient t2 = new TestClient(sn);
TestClient t3 = new TestClient(sn);
t1.start();
t2.start();
t3.start();
}
privatestatic class TestClient extends Thread
{
private SequenceNumber sn;
public TestClient(SequenceNumber sn) {
this.sn = sn;
}
public void run()
{
for (int i = 0; i < 3; i++) {
// â£æ¯ä¸ªçº¿ç¨æåº3个åºåå¼
System.out.println("thread[" + Thread.currentThread().getName()+"]sn[" + sn.getNextNum() + "]");
}
}
}
}
é常æ们éè¿å¿åå é¨ç±»çæ¹å¼å®ä¹ThreadLocalçåç±»ï¼æä¾åå§çåéå¼ï¼å¦ä¾åä¸â å¤æ示ãTestClient线ç¨äº§çä¸ç»åºåå·ï¼å¨â¢å¤ï¼æ们çæ3个TestClientï¼å®ä»¬å ±äº«åä¸ä¸ªSequenceNumberå®ä¾ãè¿è¡ä»¥ä¸ä»£ç ï¼å¨æ§å¶å°ä¸è¾åºä»¥ä¸çç»æï¼
thread[Thread-2] sn[1]
thread[Thread-0] sn[1]
thread[Thread-1] sn[1]
thread[Thread-2] sn[2]
thread[Thread-0] sn[2]
thread[Thread-1] sn[2]
thread[Thread-2] sn[3]
thread[Thread-0] sn[3]
thread[Thread-1] sn[3]
èå¯è¾åºçç»æä¿¡æ¯ï¼æ们åç°æ¯ä¸ªçº¿ç¨æ产ççåºå·è½ç¶é½å ±äº«åä¸ä¸ªSequenceNumberå®ä¾ï¼ä½å®ä»¬å¹¶æ²¡æåçç¸äºå¹²æ°çæ åµï¼èæ¯åèªäº§çç¬ç«çåºåå·ï¼è¿æ¯å 为æ们éè¿ThreadLocal为æ¯ä¸ä¸ªçº¿ç¨æä¾äºåç¬çå¯æ¬ã
Threadåæ¥æºå¶çæ¯è¾
ThreadLocalå线ç¨åæ¥æºå¶ç¸æ¯æä»ä¹ä¼å¿å¢ï¼ThreadLocalå线ç¨åæ¥æºå¶é½æ¯ä¸ºäºè§£å³å¤çº¿ç¨ä¸ç¸ååéç访é®å²çªé®é¢ã
å¨åæ¥æºå¶ä¸ï¼éè¿å¯¹è±¡çéæºå¶ä¿è¯åä¸æ¶é´åªæä¸ä¸ªçº¿ç¨è®¿é®åéãè¿æ¶è¯¥åéæ¯å¤ä¸ªçº¿ç¨å ±äº«çï¼ä½¿ç¨åæ¥æºå¶è¦æ±ç¨åºæ å¯å°åæä»ä¹æ¶å对åéè¿è¡è¯»åï¼ä»ä¹æ¶åéè¦éå®æ个对象ï¼ä»ä¹æ¶åéæ¾å¯¹è±¡éçç¹æçé®é¢ï¼ç¨åºè®¾è®¡åç¼åé¾åº¦ç¸å¯¹è¾å¤§ã
èThreadLocalåä»å¦ä¸ä¸ªè§åº¦æ¥è§£å³å¤çº¿ç¨ç并å访é®ãThreadLocalä¼ä¸ºæ¯ä¸ä¸ªçº¿ç¨æä¾ä¸ä¸ªç¬ç«çåéå¯æ¬ï¼ä»èé离äºå¤ä¸ªçº¿ç¨å¯¹æ°æ®ç访é®å²çªãå 为æ¯ä¸ä¸ªçº¿ç¨é½æ¥æèªå·±çåéå¯æ¬ï¼ä»èä¹å°±æ²¡æå¿ è¦å¯¹è¯¥åéè¿è¡åæ¥äºãThreadLocalæä¾äºçº¿ç¨å®å ¨çå ±äº«å¯¹è±¡ï¼å¨ç¼åå¤çº¿ç¨ä»£ç æ¶ï¼å¯ä»¥æä¸å®å ¨çåéå°è£ è¿ThreadLocalã
ç±äºThreadLocalä¸å¯ä»¥ææä»»ä½ç±»åç对象ï¼ä½çæ¬JDKææä¾çget()è¿åçæ¯Object对象ï¼éè¦å¼ºå¶ç±»å转æ¢ãä½JDK5.0éè¿æ³åå¾å¥½ç解å³äºè¿ä¸ªé®é¢ï¼å¨ä¸å®ç¨åº¦å°ç®åThreadLocalç使ç¨ï¼ä»£ç æ¸ å 9 2就使ç¨äºJDK5.0æ°çThreadLocal<T>çæ¬ã
æ¦æ¬èµ·æ¥è¯´ï¼å¯¹äºå¤çº¿ç¨èµæºå ±äº«çé®é¢ï¼åæ¥æºå¶éç¨äºâ以æ¶é´æ¢ç©ºé´âçæ¹å¼ï¼èThreadLocaléç¨äºâ以空é´æ¢æ¶é´âçæ¹å¼ãåè ä» æä¾ä¸ä»½åéï¼è®©ä¸åç线ç¨æé访é®ï¼èåè 为æ¯ä¸ä¸ªçº¿ç¨é½æä¾äºä¸ä»½åéï¼å æ¤å¯ä»¥åæ¶è®¿é®èäºä¸å½±åã
Spring使ç¨ThreadLocal解å³çº¿ç¨å®å ¨é®é¢
æ们ç¥éå¨ä¸è¬æ åµä¸ï¼åªææ ç¶æçBeanæå¯ä»¥å¨å¤çº¿ç¨ç¯å¢ä¸å ±äº«ï¼å¨Springä¸ï¼ç»å¤§é¨åBeané½å¯ä»¥å£°æ为singletonä½ç¨åãå°±æ¯å 为Spring对ä¸äºBeanï¼å¦RequestContextHolderãTransactionSynchronizationManagerãLocaleContextHolderçï¼ä¸é线ç¨å®å ¨ç¶æéç¨ThreadLocalè¿è¡å¤çï¼è®©å®ä»¬ä¹æ为线ç¨å®å ¨çç¶æï¼å 为æç¶æçBeanå°±å¯ä»¥å¨å¤çº¿ç¨ä¸å ±äº«äºã
ä¸è¬çWebåºç¨åå为å±ç°å±ãæå¡å±åæä¹ å±ä¸ä¸ªå±æ¬¡ï¼å¨ä¸åçå±ä¸ç¼å对åºçé»è¾ï¼ä¸å±éè¿æ¥å£åä¸å±å¼æ¾åè½è°ç¨ãå¨ä¸è¬æ åµä¸ï¼ä»æ¥æ¶è¯·æ±å°è¿åååºæç»è¿çææç¨åºè°ç¨é½åå±äºä¸ä¸ªçº¿ç¨ï¼å¦å¾9?2æ示ï¼
å¾1åä¸çº¿ç¨è´¯éä¸å±
è¿æ ·ä½ å°±å¯ä»¥æ ¹æ®éè¦ï¼å°ä¸äºé线ç¨å®å ¨çåé以ThreadLocalåæ¾ï¼å¨åä¸æ¬¡è¯·æ±ååºçè°ç¨çº¿ç¨ä¸ï¼ææå ³èç对象å¼ç¨å°çé½æ¯åä¸ä¸ªåéã
ä¸é¢çå®ä¾è½å¤ä½ç°Spring对æç¶æBeançæ¹é æè·¯ï¼
代ç æ¸ å3 TopicDaoï¼é线ç¨å®å ¨
public class TopicDao {
private Connection conn;â ä¸ä¸ªé线ç¨å®å ¨çåé
public void addTopic(){
Statement stat = conn.createStatement();â¡å¼ç¨é线ç¨å®å ¨åé
â¦
}
}
ç±äºâ å¤çconnæ¯æååéï¼å 为addTopic()æ¹æ³æ¯é线ç¨å®å ¨çï¼å¿ é¡»å¨ä½¿ç¨æ¶å建ä¸ä¸ªæ°TopicDaoå®ä¾ï¼ésingletonï¼ãä¸é¢ä½¿ç¨ThreadLocal对connè¿ä¸ªé线ç¨å®å ¨çâç¶æâè¿è¡æ¹é ï¼
代ç æ¸ å4 TopicDaoï¼çº¿ç¨å®å ¨
package threadLocalDemo;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
public class SqlConnection {
//â 使ç¨ThreadLocalä¿åConnectionåé
privatestatic ThreadLocal<Connection>connThreadLocal = newThreadLocal<Connection>();
publicstatic Connection getConnection() {
// â¡å¦æconnThreadLocal没ææ¬çº¿ç¨å¯¹åºçConnectionå建ä¸ä¸ªæ°çConnectionï¼
// 并å°å ¶ä¿åå°çº¿ç¨æ¬å°åéä¸ã
if (connThreadLocal.get() == null) {
Connection conn = getConnection();
connThreadLocal.set(conn);
return conn;
} else {
return connThreadLocal.get();
// â¢ç´æ¥è¿å线ç¨æ¬å°åé
}
}
public voidaddTopic() {
// â£ä»ThreadLocalä¸è·å线ç¨å¯¹åºçConnection
try {
Statement stat = getConnection().createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
æ们使ç¨æ¨¡æ¿ç±»è®¿é®åºå±æ°æ®ï¼æ ¹æ®æä¹ åææ¯çä¸åï¼æ¨¡æ¿ç±»éè¦ç»å®æ°æ®è¿æ¥æä¼è¯çèµæºãä½è¿äºèµæºæ¬èº«æ¯é线ç¨å®å ¨çï¼ä¹å°±æ¯è¯´å®ä»¬ä¸è½å¨åä¸æ¶å»è¢«å¤ä¸ªçº¿ç¨å ±äº«ã
è½ç¶æ¨¡æ¿ç±»éè¿èµæºæ± è·åæ°æ®è¿æ¥æä¼è¯ï¼ä½èµæºæ± æ¬èº«è§£å³çæ¯æ°æ®è¿æ¥æä¼è¯çç¼åé®é¢ï¼å¹¶éæ°æ®è¿æ¥æä¼è¯ç线ç¨å®å ¨é®é¢ã
æç §ä¼ ç»ç»éªï¼å¦ææ个对象æ¯é线ç¨å®å ¨çï¼å¨å¤çº¿ç¨ç¯å¢ä¸ï¼å¯¹å¯¹è±¡ç访é®å¿ é¡»éç¨synchronizedè¿è¡çº¿ç¨åæ¥ãä½SpringçDAO模æ¿ç±»å¹¶æªéç¨çº¿ç¨åæ¥æºå¶ï¼å 为线ç¨åæ¥éå¶äºå¹¶å访é®ï¼ä¼å¸¦æ¥å¾å¤§çæ§è½æ失ã
æ¤å¤ï¼éè¿ä»£ç åæ¥è§£å³æ§è½å®å ¨é®é¢æææ§å¾å¤§ï¼å¯è½ä¼å¢å¼ºå¥½å åçå®ç°é¾åº¦ãé£æ¨¡æ¿ç±»ç©¶ç«ä»°ä¸ä½ç§éæ³ç¥åï¼å¯ä»¥å¨æ éåæ¥çæ åµä¸å°±å解线ç¨å®å ¨çé¾é¢å¢ï¼çæ¡å°±æ¯ThreadLocalï¼
ThreadLocalå¨Springä¸åæ¥çéè¦çä½ç¨ï¼å¨ç®¡çrequestä½ç¨åçBeanãäºå¡ç®¡çãä»»å¡è°åº¦ãAOPç模åé½åºç°äºå®ä»¬ç身影ï¼èµ·ç举足轻éçä½ç¨ãè¦æ³äºè§£Springäºå¡ç®¡ççåºå±ææ¯ï¼ThreadLocalæ¯å¿ é¡»æ»å çå±±å¤´å ¡åã
ThreadLocalæ¯ä»ä¹
æ©å¨JDK1.2ççæ¬ä¸å°±æä¾java.lang.ThreadLocalï¼ThreadLocal为解å³å¤çº¿ç¨ç¨åºç并åé®é¢æä¾äºä¸ç§æ°çæè·¯ã使ç¨è¿ä¸ªå·¥å ·ç±»å¯ä»¥å¾ç®æ´å°ç¼ååºä¼ç¾çå¤çº¿ç¨ç¨åºã
ThreadLocalå¾å®¹æ让人ææçä¹ï¼æ³å½ç¶å°è®¤ä¸ºæ¯ä¸ä¸ªâæ¬å°çº¿ç¨âãå ¶å®ï¼ThreadLocal并ä¸æ¯ä¸ä¸ªThreadï¼èæ¯Threadçå±é¨åéï¼ä¹è®¸æå®å½å为ThreadLocalVariableæ´å®¹æ让人ç解ä¸äºã
å½ä½¿ç¨ThreadLocalç»´æ¤åéæ¶ï¼ThreadLocal为æ¯ä¸ªä½¿ç¨è¯¥åéç线ç¨æä¾ç¬ç«çåéå¯æ¬ï¼æ以æ¯ä¸ä¸ªçº¿ç¨é½å¯ä»¥ç¬ç«å°æ¹åèªå·±çå¯æ¬ï¼èä¸ä¼å½±åå ¶å®çº¿ç¨æ对åºçå¯æ¬ã
ä»çº¿ç¨çè§åº¦çï¼ç®æ åé就象æ¯çº¿ç¨çæ¬å°åéï¼è¿ä¹æ¯ç±»åä¸âLocalâæè¦è¡¨è¾¾çææã
线ç¨å±é¨åé并ä¸æ¯Javaçæ°åæï¼å¾å¤è¯è¨ï¼å¦IBM IBM XLFORTRANï¼å¨è¯æ³å±é¢å°±æä¾çº¿ç¨å±é¨åéãå¨Javaä¸æ²¡ææä¾å¨è¯è¨çº§æ¯æï¼èæ¯åç¸å°éè¿ThreadLocalçç±»æä¾æ¯æã
æ以ï¼å¨Javaä¸ç¼å线ç¨å±é¨åéç代ç ç¸å¯¹æ¥è¯´è¦ç¬¨æä¸äºï¼å æ¤é æ线ç¨å±é¨åé没æå¨Javaå¼åè ä¸å¾å°å¾å¥½çæ®åã
ThreadLocalçæ¥å£æ¹æ³
ThreadLocalç±»æ¥å£å¾ç®åï¼åªæ4个æ¹æ³ï¼æ们å æ¥äºè§£ä¸ä¸ï¼
void set(Object value)
设置å½å线ç¨ç线ç¨å±é¨åéçå¼ã
public Object get()
该æ¹æ³è¿åå½å线ç¨æ对åºç线ç¨å±é¨åéã
public void remove()
å°å½å线ç¨å±é¨åéçå¼å é¤ï¼ç®çæ¯ä¸ºäºåå°å åçå ç¨ï¼è¯¥æ¹æ³æ¯JDK5.0æ°å¢çæ¹æ³ãéè¦æåºçæ¯ï¼å½çº¿ç¨ç»æåï¼å¯¹åºè¯¥çº¿ç¨çå±é¨åéå°èªå¨è¢«åå¾åæ¶ï¼æ以æ¾å¼è°ç¨è¯¥æ¹æ³æ¸ é¤çº¿ç¨çå±é¨åé并ä¸æ¯å¿ é¡»çæä½ï¼ä½å®å¯ä»¥å å¿«å ååæ¶çé度ã
protected Object initialValue()
è¿å该线ç¨å±é¨åéçåå§å¼ï¼è¯¥æ¹æ³æ¯ä¸ä¸ªprotectedçæ¹æ³ï¼æ¾ç¶æ¯ä¸ºäºè®©åç±»è¦çè设计çãè¿ä¸ªæ¹æ³æ¯ä¸ä¸ªå»¶è¿è°ç¨æ¹æ³ï¼å¨çº¿ç¨ç¬¬1次è°ç¨get()æset(Object)æ¶ææ§è¡ï¼å¹¶ä¸ä» æ§è¡1次ãThreadLocalä¸ç缺çå®ç°ç´æ¥è¿åä¸ä¸ªnullã
å¼å¾ä¸æçæ¯ï¼å¨JDK5.0ä¸ï¼ThreadLocalå·²ç»æ¯ææ³åï¼è¯¥ç±»çç±»åå·²ç»å为ThreadLocal<T>ãAPIæ¹æ³ä¹ç¸åºè¿è¡äºè°æ´ï¼æ°çæ¬çAPIæ¹æ³åå«æ¯voidset(T value)ãT get()以åT initialValue()ã
ThreadLocalæ¯å¦ä½åå°ä¸ºæ¯ä¸ä¸ªçº¿ç¨ç»´æ¤åéçå¯æ¬çå¢ï¼å ¶å®å®ç°çæè·¯å¾ç®åï¼å¨ThreadLocalç±»ä¸æä¸ä¸ªMapï¼ç¨äºåå¨æ¯ä¸ä¸ªçº¿ç¨çåéå¯æ¬ï¼Mapä¸å ç´ çé®ä¸ºçº¿ç¨å¯¹è±¡ï¼èå¼å¯¹åºçº¿ç¨çåéå¯æ¬ãæ们èªå·±å°±å¯ä»¥æä¾ä¸ä¸ªç®åçå®ç°çæ¬ï¼
// 代ç æ¸ å1 SimpleThreadLocal
class SimpleThreadLocal {
private MapvalueMap = Collections.synchronizedMap(new HashMap());
public voidset(Object newValue) {
valueMap.put(Thread.currentThread(), newValue);//â é®ä¸ºçº¿ç¨å¯¹è±¡ï¼å¼ä¸ºæ¬çº¿ç¨çåéå¯æ¬
}
publicObject get() {
Thread currentThread = Thread.currentThread();
Object o = valueMap.get(currentThread);// â¡è¿åæ¬çº¿ç¨å¯¹åºçåé
if (o == null &&!valueMap.containsKey(currentThread)) {// â¢å¦æå¨Mapä¸ä¸åå¨ï¼æ¾å°Map
// ä¸ä¿åèµ·æ¥ã
o = initialValue();
valueMap.put(currentThread, o);
}
return o;
}
public voidremove() {
valueMap.remove(Thread.currentThread());
}
publicObject initialValue() {
return null;
}
}
è½ç¶ä»£ç æ¸ å9?3è¿ä¸ªThreadLocalå®ç°çæ¬æ¾å¾æ¯è¾å¹¼ç¨ï¼ä½å®åJDKææä¾çThreadLocalç±»å¨å®ç°æè·¯ä¸æ¯ç¸è¿çã
ä¸ä¸ªTheadLocalå®ä¾
ä¸é¢ï¼æ们éè¿ä¸ä¸ªå ·ä½çå®ä¾äºè§£ä¸ä¸ThreadLocalçå ·ä½ä½¿ç¨æ¹æ³
package threadLocalDemo;
public class SequenceNumber {
//â éè¿å¿åå é¨ç±»è¦çThreadLocalçinitialValue()æ¹æ³ï¼æå®åå§å¼
privatestatic ThreadLocal<Integer> seqNum =new ThreadLocal<Integer>() {
public Integer initialValue() {
return 0;
}
};
//â¡è·åä¸ä¸ä¸ªåºåå¼
public intgetNextNum() {
seqNum.set(seqNum.get() + 1);
return seqNum.get();
}
publicstatic void main(String[] args)
{
SequenceNumber sn = new SequenceNumber();
// ⢠3个线ç¨å ±äº«snï¼åèªäº§çåºåå·
TestClient t1 = new TestClient(sn);
TestClient t2 = new TestClient(sn);
TestClient t3 = new TestClient(sn);
t1.start();
t2.start();
t3.start();
}
privatestatic class TestClient extends Thread
{
private SequenceNumber sn;
public TestClient(SequenceNumber sn) {
this.sn = sn;
}
public void run()
{
for (int i = 0; i < 3; i++) {
// â£æ¯ä¸ªçº¿ç¨æåº3个åºåå¼
System.out.println("thread[" + Thread.currentThread().getName()+"]sn[" + sn.getNextNum() + "]");
}
}
}
}
é常æ们éè¿å¿åå é¨ç±»çæ¹å¼å®ä¹ThreadLocalçåç±»ï¼æä¾åå§çåéå¼ï¼å¦ä¾åä¸â å¤æ示ãTestClient线ç¨äº§çä¸ç»åºåå·ï¼å¨â¢å¤ï¼æ们çæ3个TestClientï¼å®ä»¬å ±äº«åä¸ä¸ªSequenceNumberå®ä¾ãè¿è¡ä»¥ä¸ä»£ç ï¼å¨æ§å¶å°ä¸è¾åºä»¥ä¸çç»æï¼
thread[Thread-2] sn[1]
thread[Thread-0] sn[1]
thread[Thread-1] sn[1]
thread[Thread-2] sn[2]
thread[Thread-0] sn[2]
thread[Thread-1] sn[2]
thread[Thread-2] sn[3]
thread[Thread-0] sn[3]
thread[Thread-1] sn[3]
èå¯è¾åºçç»æä¿¡æ¯ï¼æ们åç°æ¯ä¸ªçº¿ç¨æ产ççåºå·è½ç¶é½å ±äº«åä¸ä¸ªSequenceNumberå®ä¾ï¼ä½å®ä»¬å¹¶æ²¡æåçç¸äºå¹²æ°çæ åµï¼èæ¯åèªäº§çç¬ç«çåºåå·ï¼è¿æ¯å 为æ们éè¿ThreadLocal为æ¯ä¸ä¸ªçº¿ç¨æä¾äºåç¬çå¯æ¬ã
Threadåæ¥æºå¶çæ¯è¾
ThreadLocalå线ç¨åæ¥æºå¶ç¸æ¯æä»ä¹ä¼å¿å¢ï¼ThreadLocalå线ç¨åæ¥æºå¶é½æ¯ä¸ºäºè§£å³å¤çº¿ç¨ä¸ç¸ååéç访é®å²çªé®é¢ã
å¨åæ¥æºå¶ä¸ï¼éè¿å¯¹è±¡çéæºå¶ä¿è¯åä¸æ¶é´åªæä¸ä¸ªçº¿ç¨è®¿é®åéãè¿æ¶è¯¥åéæ¯å¤ä¸ªçº¿ç¨å ±äº«çï¼ä½¿ç¨åæ¥æºå¶è¦æ±ç¨åºæ å¯å°åæä»ä¹æ¶å对åéè¿è¡è¯»åï¼ä»ä¹æ¶åéè¦éå®æ个对象ï¼ä»ä¹æ¶åéæ¾å¯¹è±¡éçç¹æçé®é¢ï¼ç¨åºè®¾è®¡åç¼åé¾åº¦ç¸å¯¹è¾å¤§ã
èThreadLocalåä»å¦ä¸ä¸ªè§åº¦æ¥è§£å³å¤çº¿ç¨ç并å访é®ãThreadLocalä¼ä¸ºæ¯ä¸ä¸ªçº¿ç¨æä¾ä¸ä¸ªç¬ç«çåéå¯æ¬ï¼ä»èé离äºå¤ä¸ªçº¿ç¨å¯¹æ°æ®ç访é®å²çªãå 为æ¯ä¸ä¸ªçº¿ç¨é½æ¥æèªå·±çåéå¯æ¬ï¼ä»èä¹å°±æ²¡æå¿ è¦å¯¹è¯¥åéè¿è¡åæ¥äºãThreadLocalæä¾äºçº¿ç¨å®å ¨çå ±äº«å¯¹è±¡ï¼å¨ç¼åå¤çº¿ç¨ä»£ç æ¶ï¼å¯ä»¥æä¸å®å ¨çåéå°è£ è¿ThreadLocalã
ç±äºThreadLocalä¸å¯ä»¥ææä»»ä½ç±»åç对象ï¼ä½çæ¬JDKææä¾çget()è¿åçæ¯Object对象ï¼éè¦å¼ºå¶ç±»å转æ¢ãä½JDK5.0éè¿æ³åå¾å¥½ç解å³äºè¿ä¸ªé®é¢ï¼å¨ä¸å®ç¨åº¦å°ç®åThreadLocalç使ç¨ï¼ä»£ç æ¸ å 9 2就使ç¨äºJDK5.0æ°çThreadLocal<T>çæ¬ã
æ¦æ¬èµ·æ¥è¯´ï¼å¯¹äºå¤çº¿ç¨èµæºå ±äº«çé®é¢ï¼åæ¥æºå¶éç¨äºâ以æ¶é´æ¢ç©ºé´âçæ¹å¼ï¼èThreadLocaléç¨äºâ以空é´æ¢æ¶é´âçæ¹å¼ãåè ä» æä¾ä¸ä»½åéï¼è®©ä¸åç线ç¨æé访é®ï¼èåè 为æ¯ä¸ä¸ªçº¿ç¨é½æä¾äºä¸ä»½åéï¼å æ¤å¯ä»¥åæ¶è®¿é®èäºä¸å½±åã
Spring使ç¨ThreadLocal解å³çº¿ç¨å®å ¨é®é¢
æ们ç¥éå¨ä¸è¬æ åµä¸ï¼åªææ ç¶æçBeanæå¯ä»¥å¨å¤çº¿ç¨ç¯å¢ä¸å ±äº«ï¼å¨Springä¸ï¼ç»å¤§é¨åBeané½å¯ä»¥å£°æ为singletonä½ç¨åãå°±æ¯å 为Spring对ä¸äºBeanï¼å¦RequestContextHolderãTransactionSynchronizationManagerãLocaleContextHolderçï¼ä¸é线ç¨å®å ¨ç¶æéç¨ThreadLocalè¿è¡å¤çï¼è®©å®ä»¬ä¹æ为线ç¨å®å ¨çç¶æï¼å 为æç¶æçBeanå°±å¯ä»¥å¨å¤çº¿ç¨ä¸å ±äº«äºã
ä¸è¬çWebåºç¨åå为å±ç°å±ãæå¡å±åæä¹ å±ä¸ä¸ªå±æ¬¡ï¼å¨ä¸åçå±ä¸ç¼å对åºçé»è¾ï¼ä¸å±éè¿æ¥å£åä¸å±å¼æ¾åè½è°ç¨ãå¨ä¸è¬æ åµä¸ï¼ä»æ¥æ¶è¯·æ±å°è¿åååºæç»è¿çææç¨åºè°ç¨é½åå±äºä¸ä¸ªçº¿ç¨ï¼å¦å¾9?2æ示ï¼
å¾1åä¸çº¿ç¨è´¯éä¸å±
è¿æ ·ä½ å°±å¯ä»¥æ ¹æ®éè¦ï¼å°ä¸äºé线ç¨å®å ¨çåé以ThreadLocalåæ¾ï¼å¨åä¸æ¬¡è¯·æ±ååºçè°ç¨çº¿ç¨ä¸ï¼ææå ³èç对象å¼ç¨å°çé½æ¯åä¸ä¸ªåéã
ä¸é¢çå®ä¾è½å¤ä½ç°Spring对æç¶æBeançæ¹é æè·¯ï¼
代ç æ¸ å3 TopicDaoï¼é线ç¨å®å ¨
public class TopicDao {
private Connection conn;â ä¸ä¸ªé线ç¨å®å ¨çåé
public void addTopic(){
Statement stat = conn.createStatement();â¡å¼ç¨é线ç¨å®å ¨åé
â¦
}
}
ç±äºâ å¤çconnæ¯æååéï¼å 为addTopic()æ¹æ³æ¯é线ç¨å®å ¨çï¼å¿ é¡»å¨ä½¿ç¨æ¶å建ä¸ä¸ªæ°TopicDaoå®ä¾ï¼ésingletonï¼ãä¸é¢ä½¿ç¨ThreadLocal对connè¿ä¸ªé线ç¨å®å ¨çâç¶æâè¿è¡æ¹é ï¼
代ç æ¸ å4 TopicDaoï¼çº¿ç¨å®å ¨
package threadLocalDemo;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
public class SqlConnection {
//â 使ç¨ThreadLocalä¿åConnectionåé
privatestatic ThreadLocal<Connection>connThreadLocal = newThreadLocal<Connection>();
publicstatic Connection getConnection() {
// â¡å¦æconnThreadLocal没ææ¬çº¿ç¨å¯¹åºçConnectionå建ä¸ä¸ªæ°çConnectionï¼
// 并å°å ¶ä¿åå°çº¿ç¨æ¬å°åéä¸ã
if (connThreadLocal.get() == null) {
Connection conn = getConnection();
connThreadLocal.set(conn);
return conn;
} else {
return connThreadLocal.get();
// â¢ç´æ¥è¿å线ç¨æ¬å°åé
}
}
public voidaddTopic() {
// â£ä»ThreadLocalä¸è·å线ç¨å¯¹åºçConnection
try {
Statement stat = getConnection().createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
温馨提示:答案为网友推荐,仅供参考
第1个回答 2018-03-31
实现springMVC的多线程并发:
1、ThreadLocal为解决多线程程序的并发问题提供了一种新的思路
2、对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。
Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。
使用 Spring 可插入的 MVC 架构,可以选择是使用内置的 Spring Web 框架还可以是 Struts 这样的 Web 框架。
本回答被网友采纳