欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

java.lang.ThreadLocal類如何使用

這篇文章主要介紹了java.lang.ThreadLocal類如何使用的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇java.lang.ThreadLocal類如何使用文章都會(huì)有所收獲,下面我們一起來看看吧。

成都創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),延平企業(yè)網(wǎng)站建設(shè),延平品牌網(wǎng)站建設(shè),網(wǎng)站定制,延平網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,延平網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

一、概述

ThreadLocal是什么呢?其實(shí)ThreadLocal并非是一個(gè)線程的本地實(shí)現(xiàn)版本,它并不是一個(gè)Thread,而是threadlocalvariable(線程局部變量)。也許把它命名為ThreadLocalVar更加合適。線程局部變量(ThreadLocal)其實(shí)的功用非常簡單,就是為每一個(gè)使用該變量的線程都提供一個(gè)變量值的副本,是Java中一種較為特殊的線程綁定機(jī)制,是每一個(gè)線程都可以獨(dú)立地改變自己的副本,而不會(huì)和其它線程的副本沖突。

從線程的角度看,每個(gè)線程都保持一個(gè)對其線程局部變量副本的隱式引用,只要線程是活動(dòng)的并且 ThreadLocal 實(shí)例是可訪問的;在線程消失之后,其線程局部實(shí)例的所有副本都會(huì)被垃圾回收(除非存在對這些副本的其他引用)。

通過ThreadLocal存取的數(shù)據(jù),總是與當(dāng)前線程相關(guān),也就是說,JVM 為每個(gè)運(yùn)行的線程,綁定了私有的本地實(shí)例存取空間,從而為多線程環(huán)境常出現(xiàn)的并發(fā)訪問問題提供了一種隔離機(jī)制。

ThreadLocal是如何做到為每一個(gè)線程維護(hù)變量的副本的呢?其實(shí)實(shí)現(xiàn)的思路很簡單,在ThreadLocal類中有一個(gè)Map,用于存儲(chǔ)每一個(gè)線程的變量的副本。

概括起來說,對于多線程資源共享的問題,同步機(jī)制采用了“以時(shí)間換空間”的方式,而ThreadLocal采用了“以空間換時(shí)間”的方式。前者僅提供一份變量,讓不同的線程排隊(duì)訪問,而后者為每一個(gè)線程都提供了一份變量,因此可以同時(shí)訪問而互不影響。

二、API說明

ThreadLocal()

創(chuàng)建一個(gè)線程本地變量。

T get()

返回此線程局部變量的當(dāng)前線程副本中的值,如果這是線程第一次調(diào)用該方法,則創(chuàng)建并初始化此副本。

protected T initialValue()

返回此線程局部變量的當(dāng)前線程的初始值。最多在每次訪問線程來獲得每個(gè)線程局部變量時(shí)調(diào)用此方法一次,即線程第一次使用 get() 方法訪問變量的時(shí)候。如果線程先于 get 方法調(diào)用 set(T) 方法,則不會(huì)在線程中再調(diào)用 initialValue 方法。

若該實(shí)現(xiàn)只返回 null;如果程序員希望將線程局部變量初始化為 null 以外的某個(gè)值,則必須為 ThreadLocal 創(chuàng)建子類,并重寫此方法。通常,將使用匿名內(nèi)部類。initialValue 的典型實(shí)現(xiàn)將調(diào)用一個(gè)適當(dāng)?shù)臉?gòu)造方法,并返回新構(gòu)造的對象。

void remove()

移除此線程局部變量的值。這可能有助于減少線程局部變量的存儲(chǔ)需求。如果再次訪問此線程局部變量,那么在默認(rèn)情況下它將擁有其 initialValue。

void set(T value)

將此線程局部變量的當(dāng)前線程副本中的值設(shè)置為指定值。許多應(yīng)用程序不需要這項(xiàng)功能,它們只依賴于 initialValue() 方法來設(shè)置線程局部變量的值。

在程序中一般都重寫initialValue方法,以給定一個(gè)特定的初始值。

三、典型實(shí)例

1、Hiberante的Session 工具類HibernateUtil

這個(gè)類是Hibernate官方文檔中HibernateUtil類,用于session管理。

public class HibernateUtil {
private static Log log = LogFactory.getLog(HibernateUtil.class);
private static final SessionFactory sessionFactory; //定義SessionFactory
static {
try {
// 通過默認(rèn)配置文件hibernate.cfg.xml創(chuàng)建SessionFactory
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
log.error("初始化SessionFactory失敗!", ex);
throw new ExceptionInInitializerError(ex);
}
}
//創(chuàng)建線程局部變量session,用來保存Hibernate的Session
public static final ThreadLocal session = new ThreadLocal();
/**
* 獲取當(dāng)前線程中的Session
* @return Session
* @throws HibernateException
*/
public static Session currentSession() throws HibernateException {
Session s = (Session) session.get();
// 如果Session還沒有打開,則新開一個(gè)Session
if (s == null) {
s = sessionFactory.openSession();
session.set(s); //將新開的Session保存到線程局部變量中
}
return s;
}
public static void closeSession() throws HibernateException {
//獲取線程局部變量,并強(qiáng)制轉(zhuǎn)換為Session類型
Session s = (Session) session.get();
session.set(null);
if (s != null)
s.close();
}
}

在這個(gè)類中,由于沒有重寫ThreadLocal的initialValue()方法,則首次創(chuàng)建線程局部變量session其初始值為null,第一次調(diào)用currentSession()的時(shí)候,線程局部變量的get()方法也為null。因此,對session做了判斷,如果為null,則新開一個(gè)Session,并保存到線程局部變量session中,這一步非常的關(guān)鍵,這也是“public static final ThreadLocal session = new ThreadLocal()”所創(chuàng)建對象session能強(qiáng)制轉(zhuǎn)換為Hibernate Session對象的原因。

2、另外一個(gè)實(shí)例

創(chuàng)建一個(gè)Bean,通過不同的線程對象設(shè)置Bean屬性,保證各個(gè)線程Bean對象的獨(dú)立性。

/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-23
* Time: 10:45:02
* 學(xué)生
*/
public class Student {
private int age = 0; //年齡
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
}
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-23
* Time: 10:53:33
* 多線程下測試程序
*/
public class ThreadLocalDemo implements Runnable {
//創(chuàng)建線程局部變量studentLocal,在后面你會(huì)發(fā)現(xiàn)用來保存Student對象
private final static ThreadLocal studentLocal = new ThreadLocal();
public static void main(String[] agrs) {
ThreadLocalDemo td = new ThreadLocalDemo();
Thread t1 = new Thread(td, "a");
Thread t2 = new Thread(td, "b");
t1.start();
t2.start();
}
public void run() {
accessStudent();
}
/**
* 示例業(yè)務(wù)方法,用來測試
*/
public void accessStudent() {
//獲取當(dāng)前線程的名字
String currentThreadName = Thread.currentThread().getName();
System.out.println(currentThreadName + " is running!");
//產(chǎn)生一個(gè)隨機(jī)數(shù)并打印
Random random = new Random();
int age = random.nextInt(100);
System.out.println("thread " + currentThreadName + " set age to:" + age);
//獲取一個(gè)Student對象,并將隨機(jī)數(shù)年齡插入到對象屬性中
Student student = getStudent();
student.setAge(age);
System.out.println("thread " + currentThreadName + " first read age is:" + student.getAge());
try {
Thread.sleep(500);
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("thread " + currentThreadName + " second read age is:" + student.getAge());
}
protected Student getStudent() {
//獲取本地線程變量并強(qiáng)制轉(zhuǎn)換為Student類型
Student student = (Student) studentLocal.get();
//線程首次執(zhí)行此方法的時(shí)候,studentLocal.get()肯定為null
if (student == null) {
//創(chuàng)建一個(gè)Student對象,并保存到本地線程變量studentLocal中
student = new Student();
studentLocal.set(student);
}
return student;
}
}

運(yùn)行結(jié)果:

a is running!
thread a set age to:76
b is running!
thread b set age to:27
thread a first read age is:76
thread b first read age is:27
thread a second read age is:76
thread b second read age is:27

可以看到a、b兩個(gè)線程age在不同時(shí)刻打印的值是完全相同的。這個(gè)程序通過妙用ThreadLocal,既實(shí)現(xiàn)多線程并發(fā),游兼顧數(shù)據(jù)的安全性。

四、總結(jié)

ThreadLocal使用場合主要解決多線程中數(shù)據(jù)數(shù)據(jù)因并發(fā)產(chǎn)生不一致問題。ThreadLocal為每個(gè)線程的中并發(fā)訪問的數(shù)據(jù)提供一個(gè)副本,通過訪問副本來運(yùn)行業(yè)務(wù),這樣的結(jié)果是耗費(fèi)了內(nèi)存,單大大減少了線程同步所帶來性能消耗,也減少了線程并發(fā)控制的復(fù)雜度。

ThreadLocal不能使用原子類型,只能使用Object類型。ThreadLocal的使用比synchronized要簡單得多。

ThreadLocal和Synchonized都用于解決多線程并發(fā)訪問。但是ThreadLocal與synchronized有本質(zhì)的區(qū)別。synchronized是利用鎖的機(jī)制,使變量或代碼塊在某一時(shí)該只能被一個(gè)線程訪問。而ThreadLocal為每一個(gè)線程都提供了變量的副本,使得每個(gè)線程在某一時(shí)間訪問到的并不是同一個(gè)對象,這樣就隔離了多個(gè)線程對數(shù)據(jù)的數(shù)據(jù)共享。而Synchronized卻正好相反,它用于在多個(gè)線程間通信時(shí)能夠獲得數(shù)據(jù)共享。

Synchronized用于線程間的數(shù)據(jù)共享,而ThreadLocal則用于線程間的數(shù)據(jù)隔離。

當(dāng)然ThreadLocal并不能替代synchronized,它們處理不同的問題域。Synchronized用于實(shí)現(xiàn)同步機(jī)制,比ThreadLocal更加復(fù)雜。

五、ThreadLocal使用的一般步驟

1、在多線程的類(如ThreadDemo類)中,創(chuàng)建一個(gè)ThreadLocal對象threadXxx,用來保存線程間需要隔離處理的對象xxx。

2、在ThreadDemo類中,創(chuàng)建一個(gè)獲取要隔離訪問的數(shù)據(jù)的方法getXxx(),在方法中判斷,若ThreadLocal對象為null時(shí)候,應(yīng)該new()一個(gè)隔離訪問類型的對象,并強(qiáng)制轉(zhuǎn)換為要應(yīng)用的類型。

3、在ThreadDemo類的run()方法中,通過getXxx()方法獲取要操作的數(shù)據(jù),這樣可以保證每個(gè)線程對應(yīng)一個(gè)數(shù)據(jù)對象,在任何時(shí)刻都操作的是這個(gè)對象。

關(guān)于“java.lang.ThreadLocal類如何使用”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“java.lang.ThreadLocal類如何使用”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

文章名稱:java.lang.ThreadLocal類如何使用
當(dāng)前URL:http://www.chinadenli.net/article2/iepsic.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動(dòng)態(tài)網(wǎng)站用戶體驗(yàn)外貿(mào)建站建站公司品牌網(wǎng)站設(shè)計(jì)網(wǎng)站設(shè)計(jì)公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)