Java之——多線程中的Synchronized和volatile與面試題

1、Synchronized關(guān)鍵字

1、方法中的變量不存在非線程安全問題,都是線程安全的。

2、兩個(gè)線程訪問同一個(gè)對(duì)象中的同步方法時(shí),一定是線程安全的。

3、關(guān)鍵字synchronized取得的鎖都是對(duì)象鎖,而不是把一段代碼或方法(函數(shù))當(dāng)作鎖,哪個(gè)線程先執(zhí)行synchronized關(guān)鍵字的方法,哪個(gè)線程就持有該方法所屬對(duì)象的鎖Lock,那么其他線程只能呈等待狀態(tài),前提是多個(gè)線程訪問的是同一個(gè)對(duì)象。但如果多個(gè)線程訪問多個(gè)對(duì)象,則JVM會(huì)創(chuàng)建多個(gè)鎖。

4、調(diào)用關(guān)鍵字synchronized聲明的方法一定是排隊(duì)運(yùn)行的。另外需要牢記“共享”兩個(gè)字,只有共享資源的讀寫訪問才需要同步化,如果不是共享資源,那么根本沒同步的必要。

5、兩個(gè)線程A和B,雖然線程A先持有了Object對(duì)象的鎖,但線程B完全可以異步調(diào)用非synchronized類型的方法。

6、A線程先持有Object對(duì)象的Lock鎖,B線程可以以異步的方式調(diào)用object對(duì)象中的非synchronized類型的方法。

7、A線程先持有object對(duì)象的Lock鎖,B線程如果在這時(shí)調(diào)用Object對(duì)象中的synchronized類型的方法則需等待,也就是同步。

8、多個(gè)線程調(diào)用同一個(gè)方法時(shí),為了避免數(shù)據(jù)出現(xiàn)交叉的情況,使用synchronized關(guān)鍵字進(jìn)行同步。

9、臟讀:在讀取實(shí)例變量時(shí),此值已經(jīng)被其他線程更改過了。

10、當(dāng)A線程調(diào)用anyObject對(duì)象加入synchronized關(guān)鍵字的X方法時(shí),A線程就獲得了X方法鎖,更準(zhǔn)確的講,是獲得了對(duì)象的鎖,所以其他線程必須等A線程執(zhí)行完畢才可以調(diào)用X方法,但B線程可以隨意調(diào)用其他的非synchronized同步方法。

11、當(dāng)A線程調(diào)用anyObject對(duì)象加入synchronized關(guān)鍵字的X方法是,A線程就獲得了X方法所在的對(duì)象鎖,所以其他線程必須等A線程執(zhí)行完畢才可以調(diào)用X方法,而B線程如果調(diào)用聲明了synchronized關(guān)鍵字的非X方法時(shí),必須等A線程將X方法執(zhí)行完,也就是釋放對(duì)象鎖后調(diào)用。

12、臟讀一定會(huì)出現(xiàn)在操作實(shí)例變量的情況下,這就是不同線程爭(zhēng)搶實(shí)例變量的結(jié)果。

13、synchronized鎖重入:關(guān)鍵字synchronized擁有鎖重入的功能,也就是在使用synchronized時(shí),當(dāng)一個(gè)線程得到一個(gè)對(duì)象鎖后,再次請(qǐng)求此對(duì)象鎖時(shí)是可以再次得到該對(duì)象的鎖的。這也證明在一個(gè)synchronized方法/塊內(nèi)部調(diào)用本類其他synchronized方法/塊時(shí),是永遠(yuǎn)可以得到鎖的。

14、當(dāng)存在父子關(guān)系時(shí),子類是完全可以通過“可重入鎖”調(diào)用父類的同步方法的。

15、出現(xiàn)異常,鎖自動(dòng)釋放。

16、同步不具有繼承性。

17、當(dāng)兩個(gè)并發(fā)線程訪問同一個(gè)對(duì)象object的synchronized(this)同步代碼塊時(shí),一段時(shí)間只能有一個(gè)線程被執(zhí)行,另一個(gè)線程必須等待當(dāng)前線程執(zhí)行完這個(gè)代碼以后才能執(zhí)行改代碼塊。

18、當(dāng)一個(gè)線程訪問object的synchronized同步代碼塊時(shí),另一個(gè)線程仍然可以訪問object中的非synchronized(this)同步代碼塊。

19、當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí),其他線程對(duì)同一個(gè)object中所有其他synchronized(this)同步代碼塊的訪問將被阻塞。這說明synchronized使用的“對(duì)象監(jiān)視器”是一個(gè)。

20、和synchronized方法一樣,synchronized(this)代碼塊也是鎖當(dāng)前對(duì)象的。

21、使用synchronized(非this對(duì)象X)格式同步代碼時(shí),對(duì)象監(jiān)視器必須是同一個(gè)對(duì)象。否則,結(jié)果就是異步調(diào)用,會(huì)交叉運(yùn)行。

22、synchronized加到static靜態(tài)方法上,是給Class上鎖,加到非static靜態(tài)方法上,是給對(duì)象上鎖。

23、同步synchronized(class)的作用實(shí)際上和synchronized static的作用類似。

24、JVM中具有Spring常量池緩存的功能

25、在將任何數(shù)據(jù)類型作為同步鎖時(shí),需要注意的是,是否有多個(gè)線程同時(shí)持有鎖對(duì)象,如果同時(shí)持有相同的鎖對(duì)象,則這些線程之間就是同步的。如果分別獲得所對(duì)象,則這些線程之間就是異步的。

26、只有鎖對(duì)象不變,即使對(duì)象的屬性變化,那么線程之前還是同步的。

在此我向大家推薦一個(gè)架構(gòu)學(xué)習(xí)交流群。交流學(xué)習(xí)群號(hào):575745314 里面會(huì)分享一些資深架構(gòu)師錄制的視頻錄像:有Spring,MyBatis,Netty源碼分析,高并發(fā)、高性能、分布式、微服務(wù)架構(gòu)的原理,JVM性能優(yōu)化、分布式架構(gòu)等這些成為架構(gòu)師必備的知識(shí)體系。還能領(lǐng)取免費(fèi)的學(xué)習(xí)資源,目前受益良多

2、volatile關(guān)鍵字

1、volatile可以使變量在多個(gè)線程間可見。

2、強(qiáng)制從公共堆棧中取得變量的值,而不是從線程私有數(shù)據(jù)棧中獲取數(shù)據(jù)。

3、增加了實(shí)例變量在多個(gè)線程之間的可見性,但是不支持原子性。

4、使用場(chǎng)合是在多個(gè)線程中可以感知實(shí)例變量被更改了,并且可以獲取最新的值使用,也就是用多線程獲取共享變量時(shí),可以獲得最新值使用。

3、面試題

1、什么是線程,什么是進(jìn)程,它們有什么區(qū)別和聯(lián)系,一個(gè)進(jìn)程里面是否必須有個(gè)線程

進(jìn)程本質(zhì)是一個(gè)正在執(zhí)行的程序,一個(gè)進(jìn)程可以有多個(gè)線程.線程是進(jìn)程的最小執(zhí)行單位,一個(gè)進(jìn)程至少有一個(gè)線程

區(qū)別:1:多進(jìn)程程序不受java控制,而多線程則受java控制,

2:多線程比多進(jìn)程需要更少的管理成本

2、實(shí)現(xiàn)一個(gè)線程有哪幾種方式,各有什么優(yōu)缺點(diǎn),比較常用的是那種,為什么

實(shí)現(xiàn)一個(gè)線程有三種方式:

1) ? ? ?繼承Thread類,需要重寫run方法,無返回值

a) ? ? ? ?優(yōu)點(diǎn):可以直接調(diào)用start方法啟動(dòng)線程

b) ? ? ? ?缺點(diǎn):java只能單繼承,如果已經(jīng)有了父類,不能用這種方法

2) ? ? ?實(shí)現(xiàn)Runnable接口,需要重寫run()方法

a) ? ? ? ?優(yōu)點(diǎn):即使自己定義的線程類有了父類也可以實(shí)現(xiàn)接口,而且接口是多實(shí)現(xiàn)

b) ? ? ? ?缺點(diǎn):需通過構(gòu)造一個(gè)Thread把自己傳進(jìn)去,才能實(shí)現(xiàn)Thread的方法,代碼復(fù)雜

3) ? ? ?實(shí)現(xiàn)Callable接口,需要重寫call()方法

a) ? ? ? ?優(yōu)點(diǎn):可以拋出異常,有返回值

b) ? ? ? ?缺點(diǎn):只有jdk1.5以后才支持,結(jié)合FuntureTask和Thread類一起使用,最后調(diào)用start啟動(dòng)線程

一般用第二種,實(shí)現(xiàn)Runnable接口,比較方便,擴(kuò)展性高

3、一般情況下我們實(shí)現(xiàn)自己線程時(shí)候要重寫什么方法

使用Thread類,要重寫run()方法

實(shí)現(xiàn)Runnable接口時(shí),要實(shí)現(xiàn)run()方法

使用Callable接口時(shí),要重寫call()方法

4、start方法和run方法有什么區(qū)別,我們一般調(diào)用的那個(gè)方法,系統(tǒng)調(diào)用的是那個(gè)方法

Start用來啟動(dòng)線程

當(dāng)調(diào)用start后,線程并不會(huì)馬上運(yùn)行,而是處于就緒狀態(tài),是否要運(yùn)行取決于cpu

Run用來子類重寫來實(shí)現(xiàn)線程的功能

我們一般調(diào)用的是start方法,系統(tǒng)調(diào)用的是run方法

5、sleep方法有什么作用,一般用來做什么

Sleep是一個(gè)Thread類的靜態(tài)方法

作用:讓調(diào)用它的線程休眠指定的時(shí)間,用于暫停線程,但不會(huì)把線程鎖讓給其它線程,休眠時(shí)間結(jié)束,線程進(jìn)入就緒狀態(tài),等待cpu分配的執(zhí)行機(jī)會(huì)

6、講下join,yield方法的作用,以及什么場(chǎng)合用它們

Join()有嚴(yán)格的先后順序,調(diào)用它的線程需要執(zhí)行完,其它線程才會(huì)執(zhí)行

Yield()是暫停當(dāng)前正在執(zhí)行的線程對(duì)象,把時(shí)間讓給其它線程

7、線程中斷是否能直接調(diào)用stop,為什么?

線程終端不能直接調(diào)用stop()方法

Stop()方法是從外部強(qiáng)行終止一個(gè)線程,會(huì)導(dǎo)致不可預(yù)知的錯(cuò)誤,比如線程鎖沒有歸還,io流不能關(guān)流

線程只能調(diào)用interrupt()方法中斷,而且不是立即中斷,(

只是發(fā)出了一個(gè)類似于信號(hào)量的東西,通過修改了被調(diào)用線程的中斷狀態(tài)來告知那個(gè)線程,說它被中斷了,至于什么時(shí)候中斷,這個(gè)系統(tǒng)會(huì)判斷)系統(tǒng)會(huì)在一個(gè)合適的時(shí)候進(jìn)行中斷處理

8、列舉出一般情況下線程中斷的幾種方式,并說明他們之間的優(yōu)缺點(diǎn),并且說明那種中斷方式最好

線程中斷有4種方式

由interrupt發(fā)出中斷信號(hào),用戶接收中斷信號(hào),通過isInterrupted判斷線程是否中斷

由interrupt發(fā)出中斷信號(hào),系統(tǒng)接收中斷信號(hào),通過sleep拋出中斷異常,并把中斷信號(hào)清除,只能拋出一次

用戶自定義中斷,將中斷信號(hào)發(fā)出,自己接收該中斷信號(hào)

調(diào)用interrupted(),會(huì)把中斷信號(hào)清除,并中斷線程

9、線程有幾種狀態(tài),他們是怎么轉(zhuǎn)化的

線程一般分為:新生,就緒,運(yùn)行,阻塞,死亡五中狀態(tài)

當(dāng)創(chuàng)建一個(gè)線程后,并沒有運(yùn)行,處于新生狀態(tài),需要通過調(diào)用start方法,讓線程處于就緒狀態(tài),但是否運(yùn)行取決于cpu分配的執(zhí)行機(jī)會(huì),當(dāng)?shù)玫絚pu的執(zhí)行機(jī)會(huì)后馬上運(yùn)行,一個(gè)正在執(zhí)行的線程可以通過很多方式進(jìn)入阻塞狀態(tài),當(dāng)執(zhí)行完所有操作后就進(jìn)入死亡狀態(tài)

10、在實(shí)現(xiàn)Runnable的接口中怎么樣訪問當(dāng)前線程對(duì)象,比如拿到當(dāng)前線程的名字

通過Thread.currentThread().getName()可獲得當(dāng)前線程名字

11、講下什么是守護(hù)線程,以及在什么場(chǎng)合來使用它

守護(hù)線程是用來監(jiān)聽其它線程是否掛掉,這個(gè)線程具有最低優(yōu)先級(jí)

用于為系統(tǒng)中的其它線程提供服務(wù)

守護(hù)線程就像象棋里的車馬相仕,非守護(hù)線程就是老帥,老帥掛掉,守護(hù)線程也就掛掉了

當(dāng)主線程和主線程創(chuàng)建的子線程全部退出,守護(hù)線程一定會(huì)跟著退出

(比如QQ主程序和QQ聊天窗口,主程序退出,QQ聊天窗口也隨之關(guān)掉)

12、一般的線程優(yōu)先級(jí)是什么回事,線程優(yōu)先級(jí)高的線程一定會(huì)先執(zhí)行嗎?如果不設(shè)置優(yōu)先級(jí)的話,那么線程優(yōu)先級(jí)是多少,設(shè)置線程優(yōu)先級(jí)用那個(gè)函數(shù)

線程的優(yōu)先級(jí)就是設(shè)置哪個(gè)線程先執(zhí)行,但不是絕對(duì),只是讓優(yōu)先級(jí)高的線程優(yōu)先運(yùn)行的概率高一些,

線程默認(rèn)優(yōu)先級(jí)是NORM_PRIORITY = 5;

最小是 MIN_PRIORITY = 1;

最大是 MAX_PRIORITY = 10;

設(shè)置線程優(yōu)先級(jí)有setPriority()方法

13、為什么Thread里面的大部分方法都是final的

線程很多方法都是由系統(tǒng)調(diào)用的,不能通過子類重寫去改變他們的行為

14、什么是線程同步,什么是線程安全

同步:當(dāng)兩個(gè)或兩個(gè)以上的線程需要共享資源,通過同步方法限制資源在一次僅被一個(gè)線程占用

線程安全:線程安全就是多線程操作同一個(gè)對(duì)象不會(huì)產(chǎn)生數(shù)據(jù)污染,

線程同步一般來保護(hù)線程安全,final修飾的也是線程安全

15、講下同步方法和同步塊的區(qū)別,以及什么時(shí)候用它們

同步方法:被synchronized修飾的方法,同步整個(gè)方法,且整個(gè)方法都會(huì)被鎖住,同一時(shí)間只有一個(gè)線程可以訪問該方法,

同步塊: 被synchronized修飾的代碼塊,可以同步一小部分代碼

什么時(shí)候用?

同步塊越小性能越好,當(dāng)性能要求比較高,用同步代碼塊

16、簡(jiǎn)單說下Lock對(duì)象的實(shí)現(xiàn)類的鎖機(jī)制和同步方法或同步塊有什么區(qū)別

是JDK1.5才出現(xiàn)的,Lock對(duì)象比synchronized更加靈活,可以控制什么時(shí)候上鎖,什么時(shí)候解鎖,而使用synchronized必須等代碼執(zhí)行完才會(huì)解鎖.

Synchronized在鎖定時(shí)如果方法塊拋出異常,JVM會(huì)自動(dòng)釋放鎖,而Lock出現(xiàn)異常必須在finally將鎖釋放,否則將引起死鎖

17、同步塊里面的同步監(jiān)視器是怎么寫的,默認(rèn)的同步方法里面的同步監(jiān)視器是那個(gè)

Synchronized(對(duì)象){

//代碼塊

}

默認(rèn)的同步監(jiān)視器是this

18、講下什么是死鎖,死鎖發(fā)生的幾個(gè)條件是什么

死鎖就是當(dāng)有兩個(gè)或兩個(gè)以上的線程都獲得對(duì)方的資源,但彼此都不肯放開,處于僵持階段,此時(shí)就造成了死鎖

條件:兩個(gè)或兩個(gè)以上的線程,同時(shí)想要獲得對(duì)方的資源,彼此又不肯放開

19、線程間是怎么通信的,通過調(diào)用幾個(gè)方法來交互的

線程是通過wait , notify等方法相互作用進(jìn)行協(xié)作通信;

wait()方法使得當(dāng)前線程必須要等待,直到到另外一個(gè)線程調(diào)用notify()或者notifyAll()方法喚醒

-- wait()和notify()方法要求在調(diào)用時(shí)線程已經(jīng)獲得了對(duì)象鎖,因此對(duì)這兩個(gè)方法的調(diào)用需要放在synchronized修飾的方法或代碼塊中。

20、wait,notify,notifyAll在什么地方使用才有效,他們是那個(gè)類的方法

Wait,notify,notifyAll都必須在synchronized修飾的方法或代碼塊中使用,都屬于Object的方法,可以被所有類繼承,都是final修飾的方法,不能通過子類重寫去改變他們的行為

21、wait和sleep有什么區(qū)別和聯(lián)系,他們執(zhí)行的時(shí)候是否都會(huì)釋放鎖

Wait和sleep都可以使線程暫停,但wait必須在synchronized修飾的方法或代碼塊中使用,

Sleep()方法是線程類的靜態(tài)方法,調(diào)用此方法會(huì)讓當(dāng)前線程暫停執(zhí)行指定的時(shí)間,將執(zhí)行機(jī)會(huì)(CPU)讓給其它線程,但是對(duì)象的鎖依然保持,因此休眠時(shí)間結(jié)束后會(huì)自動(dòng)恢復(fù)(就緒狀態(tài)),

wait()是Object類的方法,調(diào)用對(duì)象的wait()方法會(huì)讓當(dāng)前線程放棄對(duì)象的鎖(線程暫停執(zhí)行),進(jìn)入對(duì)象的等待池(wait pool),只有調(diào)用對(duì)象的Notify()或notifyAll()方法才能喚醒等待池中的線程進(jìn)入等鎖池(lock pool),如果線程重新獲得對(duì)象的鎖就可以進(jìn)入就緒狀態(tài)

22、yield,sleep方法有什么區(qū)別和聯(lián)系

Yield和sleep都可以讓線程暫停,

1) ? ? ?Sleep()方法給其它線程運(yùn)行機(jī)會(huì)時(shí)不考慮線程的優(yōu)先級(jí),因此會(huì)給低優(yōu)先級(jí)的線程以運(yùn)行機(jī)會(huì)…yield()方法只會(huì)給相同優(yōu)先級(jí)或更高優(yōu)先級(jí)的線程以運(yùn)行機(jī)會(huì)

2) ? ? ?線程執(zhí)行sleep()方法后轉(zhuǎn)入阻塞狀態(tài),而執(zhí)行yield()方法后轉(zhuǎn)入就緒狀態(tài)

3) ? ? ?Sleep()方法聲明拋出InterruptedException,而yield()方法沒有聲明任何異常

4) ? ? ?Sleep()方法比yield()方法具有更好的可移植性

23、線程的啟動(dòng)是哪個(gè)方法,調(diào)用的是哪個(gè)方法?

Start用于啟動(dòng)線程,當(dāng)調(diào)用start后,線程并不會(huì)馬上運(yùn)行,而是處于就緒狀態(tài),是否運(yùn)行取決于cpu給的時(shí)間片

Run()方法用于子類重寫來實(shí)現(xiàn)線程的功能

我們一般調(diào)用的是start方法,系統(tǒng)調(diào)用的是run方法

24、線程安全與線程不安全的區(qū)別

線程安全就是多線程訪問時(shí),采用了加鎖機(jī)制,

當(dāng)一個(gè)線程訪問類中某個(gè)數(shù)據(jù),進(jìn)行保護(hù),其它線程不能進(jìn)行訪問,直到該線程執(zhí)行完,其它線程才可使用---不會(huì)導(dǎo)致數(shù)據(jù)污染

線程不安全就是不提供數(shù)據(jù)訪問保護(hù),有可能出現(xiàn)多個(gè)線程先后更改數(shù)據(jù)造成所得到的數(shù)據(jù)是臟數(shù)據(jù)

25、線程的實(shí)現(xiàn)方式,線程的生命周期等

實(shí)現(xiàn)方式

1) ?通過繼承Thread類

2) ?實(shí)現(xiàn)Runnable接口

3) ?實(shí)現(xiàn)Callable接口

生命周期

新建

就緒

運(yùn)行

堵塞

死亡

26、如何處理線程不安全問題(有2種解決方法)

第一,是采用原子變量,線程安全問題最根本上是由于全局變量和靜態(tài)變量引起的,定義變量用sig_atomic_t和volatile。

第二,就是實(shí)現(xiàn)線程間同步,讓線程有序訪問變量

27、線程中常用方法的區(qū)別

線程中用到最多的是start方法,它的作用是啟動(dòng)一個(gè)線程

Sleep()讓線程休眠一會(huì),但不會(huì)釋放鎖

Join()強(qiáng)制執(zhí)行一個(gè)線程

Wait()是Object類中的方法,會(huì)讓當(dāng)前線程放棄對(duì)象鎖,進(jìn)入對(duì)象等待池

Yield()禮讓線程,讓另外一個(gè)線程執(zhí)行一會(huì),自己再執(zhí)行,只能讓同優(yōu)先級(jí)的線程有執(zhí)行的機(jī)會(huì)

currentThread()用于獲得當(dāng)前線程對(duì)象,可以調(diào)用getName()方法獲得當(dāng)前線程名字

28、多線程和單線程有什么區(qū)別?

干一件事情一個(gè)人干和兩個(gè)人同時(shí)干的區(qū)別

29、線程的5種狀態(tài),__、_、_、___。啟動(dòng)調(diào)用_方法,啟動(dòng)后會(huì)調(diào)用__方法。

新生

就緒

運(yùn)行

阻塞

死亡

啟動(dòng)調(diào)用start()

30、用同步塊與同步方法的區(qū)別?

同步方法是被synchronized修飾的方法,同步整個(gè)方法, ,同一時(shí)間只有一個(gè)線程可以訪問該方法

同步塊是被synchronized修飾的代碼塊,可以同步一小部分代碼

同步代碼越少性能越好,當(dāng)性能要求比較高時(shí),用同步塊

31、寫二個(gè)線程,對(duì)一個(gè)int類型一個(gè)i++,一個(gè)i--

32、說說stop為什么不建議使用。

Stop()方法是從外部強(qiáng)行終止一個(gè)線程,會(huì)導(dǎo)致不可預(yù)知的錯(cuò)誤,比如線程鎖沒有歸還,io流不能關(guān)流

線程只能調(diào)用interrupt()方法中斷,而且不是立即中斷,(

只是發(fā)出了一個(gè)類似于信號(hào)量的東西,通過修改了被調(diào)用線程的中斷狀態(tài)來告知那個(gè)線程,說它被中斷了,至于什么時(shí)候中斷,這個(gè)系統(tǒng)會(huì)判斷)系統(tǒng)會(huì)在一個(gè)合適的時(shí)候進(jìn)行中斷處理

33、Runable接口的方法是什么?

Run

34、什么是同步和異步,分別用例子說明,同步有幾種方式?

同步是排隊(duì)去做事情,異步就是各做各的

35、什么是對(duì)象鎖?

1. ? java中的每個(gè)對(duì)象都有一個(gè)鎖,當(dāng)訪問某個(gè)對(duì)象的synchronized方法時(shí),表示將該對(duì)象上鎖,此時(shí)其他任何線程都無法在去訪問該syncronized 方法了,直到之前的那個(gè)線程執(zhí)行方法完畢后,其他線程才有可能去訪問該synchronized方法。

2.如果一個(gè)對(duì)象有多個(gè)synchronized方法,某一時(shí)刻某個(gè)線程已經(jīng)進(jìn)入到某個(gè)synchronzed方法,那么在該方法沒有執(zhí)行完畢前,其他線程無法訪問該對(duì)象的任何synchronzied 方法的,但可以訪問非synchronzied方法。

3.如果synchronized方法是static的,那么當(dāng)線程訪問該方法時(shí),它鎖的并不是synchronized方法所在的對(duì)象,而是synchuronized方法所在對(duì)象的對(duì)應(yīng)的Class對(duì)象,

[類鎖(synchronized修飾的靜態(tài)方法)]

36、什么是死鎖?

死鎖就是當(dāng)有兩個(gè)或兩個(gè)以上的線程都獲得對(duì)方的資源,但彼此有不肯放開,處于僵持狀態(tài),此時(shí)便造成了死鎖。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容