【秋招必備】Java並發編程面試題(2021最新版)


前言

多線程和並發問題是Java技術面試中面試官比較喜歡問的問題之一。在這里,從面試的角度列出了大部分重要的問題,但是你仍然應該牢固的掌握Java多線程基礎知識來對應日后碰到的問題。

小編分享的這份Java后端開發面試總結包含了JavaOOP、Java集合容器、Java異常、並發編程、Java反射、Java序列化、JVM、Redis、Spring MVC、MyBatis、MySQL數據庫、消息中間件MQ、Dubbo、Linux、ZooKeeper、 分布式&數據結構與算法等26個專題技術點,都是小編在各個大廠總結出來的面試真題,已經有很多粉絲靠這份PDF拿下眾多大廠的offer,今天在這里總結分享給到大家!【已完結】

完整版Java面試題地址:2021最新面試題合集集錦

序號 專題 內容 鏈接
1 中間件 【秋招必備】Java中間件面試題(2021最新版) https://www.cnblogs.com/QLCZ/p/14851355.html
2 微服務 【秋招必備】Java微服務面試題(2021最新版) https://www.cnblogs.com/QLCZ/p/14893883.html
3 並發編程 【秋招必備】Java並發編程面試題(2021最新版) 待更新
4 Java基礎 【秋招必備】Java基礎知識面試題(2021最新版) 待更新
5 Spring Boot 【秋招必備】Spring Boot面試題(2021最新版) 待更新
6 Redis 【秋招必備】Redis面試題(2021最新版) 待更新
7 Spring MVC 【秋招必備】Spring MVC面試題(2021最新版) 待更新
8 Spring Cloud 【秋招必備】Spring Cloud面試題(2021最新版) 待更新
9 MySQL優化 【秋招必備】MySQL優化面試題(2021最新版) 待更新
10 JVM 【秋招必備】JVM性能調優面試題(2021最新版) 待更新
11 Linux 【秋招必備】Linux面試題(2021最新版) 待更新
12 Mybatis 【秋招必備】Mybatis面試題(2021最新版) 待更新
13 網絡編程 【秋招必備】TCP,UDP,Socket,Http網絡編程面試題(2021最新版) 待更新
14 設計模式 【秋招必備】設計模式面試題(2021最新版) 待更新
15 大數據 【秋招必備】大數據面試題100道(2021最新版) 待更新
16 Tomcat 【秋招必備】Tomcat面試題(2021最新版) 待更新
17 多線程 【秋招必備】多線程面試題(2021最新版) 待更新
18 Nginx 【秋招必備】Nginx_BIO_NIO_AIO面試題(2021最新版) 待更新
19 memcache 【秋招必備】memcache面試題(2021最新版) 待更新
20 java異常 【秋招必備】java異常面試題(2021最新版) 待更新
21 Java虛擬機 【秋招必備】Java虛擬機面試題(2021最新版) 待更新
22 Java集合 【秋招必備】Java集合面試題(2021最新版) 待更新
23 Git常用命令 【秋招必備】Git常用命令(2021最新版) 待更新
24 Elasticsearch 【秋招必備】Elasticsearch面試題(2021最新版) 待更新
25 Dubbo 【秋招必備】Dubbo面試題(2021最新版) 待更新

一、基礎知識

1. 為什么要使用並發編程

  • 充分利用多核CPU的計算能力:通過並發編程的形式可以將多核CPU的計算能力發揮到極致,性能得到提升
  • 方便進行業務拆分,提升系統並發能力和性能:在特殊的業務場景下,先天的就適合於並發編程。現在的系統動不動就要求百萬級甚至千萬級的並發量,而多線程並發編程正是開發高並發系統的基礎,利用好多線程機制可以大大提高系統整體的並發能力以及性能。面對復雜業務模型,並行程序會比串行程序更適應業務需求,而並發編程更能吻合這種業務拆分 。

2. 多線程應用場景

3. 並發編程有什么缺點

並發編程的目的就是為了能提高程序的執行效率,提高程序運行速度,但是並發編程並不總是能提高程序運行速度的,而且並發編程可能會遇到很多問題,比如**:內存泄漏、上下文切換、線程安全、死鎖**等問題。

4. 並發編程三個必要因素是什么?

並發編程三要素(線程的安全性問題體現在):

原子性:原子,即一個不可再被分割的顆粒。原子性指的是一個或多個操作要么全部執行成功要么全部執行失敗。

可見性:一個線程對共享變量的修改,另一個線程能夠立刻看到。(synchronized,volatile)

有序性:程序執行的順序按照代碼的先后順序執行。(處理器可能會對指令進行重排序)

出現線程安全問題的原因:

  • 線程切換帶來的原子性問題
  • 緩存導致的可見性問題
  • 編譯優化帶來的有序性問題

解決辦法:

  • JDK Atomic開頭的原子類、synchronized、LOCK,可以解決原子性問題
  • synchronized、volatile、LOCK,可以解決可見性問題
  • Happens-Before 規則可以解決有序性問題

5. Java 程序中怎么保證多線程的運行安全?

6. 並行和並發有什么區別?

7. 什么是多線程

多線程:多線程是指程序中包含多個執行流,即在一個程序中可以同時運行多個不同的線程來執行不同的任務。

8. 多線程的好處

可以提高 CPU 的利用率。在多線程程序中,一個線程必須等待的時候,CPU 可以運行其它的線程而不是等待,這樣就大大提高了程序的效率。也就是說允許單個程序創建多個並行執行的線程來完成各自的任務。

9. 多線程的劣勢:

  • 線程也是程序,所以線程需要占用內存,線程越多占用內存也越多;
  • 多線程需要協調和管理,所以需要 CPU 時間跟蹤線程;
  • 線程之間對共享資源的訪問會相互影響,必須解決競用共享資源的問題。

10. 線程和進程區別

進程

一個在內存中運行的應用程序。每個進程都有自己獨立的一塊內存空間,一個進程可以有多個線程,比如在Windows系統中,一個運行的xx.exe就是一個進程。

線程

進程中的一個執行任務(控制單元),負責當前進程中程序的執行。一個進程至少有一個線程,一個進程可以運行多個線程,多個線程可共享數據。

線程具有許多傳統進程所具有的特征,故又稱為輕型進程(Light—Weight Process)或進程元;而把傳統的進程稱為重型進程(Heavy—Weight Process),它相當於只有一個線程的任務。在引入了線程的操作系統中,通常一個進程都有若干個線程,至少包含一個線程。

根本區別:進程是操作系統資源分配的基本單位,而線程是處理器任務調度和執行的基本單位

資源開銷:每個進程都有獨立的代碼和數據空間(程序上下文),程序之間的切換會有較大的開銷;線程可以看做輕量級的進程,同一類線程共享代碼和數據空間,每個線程都有自己獨立的運行棧和程序計數器(PC),線程之間切換的開銷小。

包含關系:如果一個進程內有多個線程,則執行過程不是一條線的,而是多條線(線程)共同完成的;線程是進程的一部分,所以線程也被稱為輕權進程或者輕量級進程。

內存分配:同一進程的線程共享本進程的地址空間和資源,而進程之間的地址空間和資源是相互獨立的

影響關系:一個進程崩潰后,在保護模式下不會對其他進程產生影響,但是一個線程崩潰整個進程都死掉。所以多進程要比多線程健壯。

執行過程:每個獨立的進程有程序運行的入口、順序執行序列和程序出口。但是線程不能獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制,兩者均可並發執行

11. 什么是上下文切換?

多線程編程中一般線程的個數都大於 CPU 核心的個數,而一個 CPU 核心在任意時刻只能被一個線程使用,為了讓這些線程都能得到有效執行,CPU 采取的策略是為每個線程分配時間片並輪轉的形式。當一個線程的時間片用完的時候就會重新處於就緒狀態讓給其他線程使用,這個過程就屬於一次上下文切換。

概括來說就是:當前任務在執行完 CPU 時間片切換到另一個任務之前會先保存自己的狀態,以便下次再切換回這個任務時,可以再加載這個任務的狀態。任務從保存到再加載的過程就是一次上下文切換

上下文切換通常是計算密集型的。也就是說,它需要相當可觀的處理器時間,在每秒幾十上百次的切換中,每次切換都需要納秒量級的時間。所以,上下文切換對系統來說意味着消耗大量的 CPU 時間,事實上,可能是操作系統中時間消耗最大的操作。

Linux 相比與其他操作系統(包括其他類 Unix 系統)有很多的優點,其中有一項就是,其上下文切換和模式切換的時間消耗非常少。

12. 守護線程和用戶線程有什么區別呢?

守護線程和用戶線程

  • 用戶 (User) 線程:運行在前台,執行具體的任務,如程序的主線程、連接網絡的子線程等都是用戶線程
  • 守護 (Daemon) 線程:運行在后台,為其他前台線程服務。也可以說守護線程是 JVM 中非守護線程的 “佣人”。一旦所有用戶線程都結束運行,守護線程會隨 JVM 一起結束工作

main 函數所在的線程就是一個用戶線程啊,main 函數啟動的同時在 JVM 內部同時還啟動了好多守護線程,比如垃圾回收線程。

比較明顯的區別之一是用戶線程結束,JVM 退出,不管這個時候有沒有守護線程運行。而守護線程不會影響 JVM 的退出。

注意事項:

  1. setDaemon(true)必須在start()方法前執行,否則會拋出 IllegalThreadStateException 異常
  2. 在守護線程中產生的新線程也是守護線程
  3. 不是所有的任務都可以分配給守護線程來執行,比如讀寫操作或者計算邏輯
  4. 守護 (Daemon) 線程中不能依靠 finally 塊的內容來確保執行關閉或清理資源的邏輯。因為我們上面也說過了一旦所有用戶線程都結束運行,守護線程會隨 JVM 一起結束工作,所以守護 (Daemon) 線程中的 finally 語句塊可能無法被執行。

13. 如何在 Windows 和 Linux 上查找哪個線程cpu利用率最高?

14. 什么是線程死鎖

15. 形成死鎖的四個必要條件是什么

  • 互斥條件:在一段時間內某資源只由一個進程占用。如果此時還有其它進程請求資源,就只能等待,直至占有資源的進程用畢釋放。
  • 占有且等待條件:指進程已經保持至少一個資源,但又提出了新的資源請求,而該資源已被其它進程占有,此時請求進程阻塞,但又對自己已獲得的其它資源保持不放。
  • 不可搶占條件:別人已經占有了某項資源,你不能因為自己也需要該資源,就去把別人的資源搶過來。
  • 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。(比如一個進程集合,A在等B,B在等C,C在等A)

16. 如何避免線程死鎖

  1. 避免一個線程同時獲得多個鎖
  2. 避免一個線程在鎖內同時占用多個資源,盡量保證每個鎖只占用一個資源
  3. 嘗試使用定時鎖,使用lock.tryLock(timeout)來替代使用內部鎖機制

17. 創建線程的四種方式

  • 繼承 Thread 類;
public class MyThread extends Thread {
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName() + " run()方法正在執
行...");
	}
  • 實現 Runnable 接口;
public class MyRunnable implements Runnable {
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName() + " run()方法執行
中...");
	}
  • 實現 Callable 接口;
public class MyCallable implements Callable<Integer> {
	@Override
	public Integer call() {
		System.out.println(Thread.currentThread().getName() + " call()方法執行
中...");
		return 1;
	}
  • 使用匿名內部類方式
public class CreateRunnable {
	public static void main(String[] args) {
		//創建多線程創建開始
		Thread thread = new Thread(new Runnable() {
			public void run() {
				for (int i = 0; i < 10; i++) {
					System.out.println("i:" + i);
				}
			}
		}
		);
		thread.start();
	}
}

18. 說一下 runnable 和 callable 有什么區別

19. 線程的 run()和 start()有什么區別?

  • 每個線程都是通過某個特定Thread對象所對應的方法run()來完成其操作的,run()方法稱為線程體。通過調用Thread類的start()方法來啟動一個線程。
  • start() 方法用於啟動線程,run() 方法用於執行線程的運行時代碼。run() 可以重復調用,而 start()只能調用一次。
  • start()方法來啟動一個線程,真正實現了多線程運行。調用start()方法無需等待run方法體代碼執行完畢,可以直接繼續執行其他的代碼; 此時線程是處於就緒狀態,並沒有運行。 然后通過此Thread類調用方法run()來完成其運行狀態, run()方法運行結束, 此線程終止。然后CPU再調度其它線程。
  • run()方法是在本線程里的,只是線程里的一個函數,而不是多線程的。 如果直接調用run(),其實就相當於是調用了一個普通函數而已,直接待用run()方法必須等待run()方法執行完畢才能執行下面的代碼,所以執行路徑還是只有一條,根本就沒有線程的特征,所以在多線程執行時要使用 start()方法而不是run()方法。

20. 為什么我們調用 start() 方法時會執行 run() 方法,為什么我們不能直接調用 run() 方法?

21. 什么是 Callable 和 Future?

  • Callable 接口類似於 Runnable,從名字就可以看出來了,但是 Runnable 不會返回結果,並且無法拋出返回結果的異常,而 Callable 功能更強大一些,被線程執行后,可以返回值,這個返回值可以被 Future 拿到,也就是說,Future 可以拿到異步執行任務的返回值。
  • Future 接口表示異步任務,是一個可能還沒有完成的異步任務的結果。所以說 Callable用於產生結果,Future 用於獲取結果。

22. 什么是 FutureTask

  • FutureTask 表示一個異步運算的任務。FutureTask 里面可以傳入一個 Callable 的具體實現類,可以對這個異步運算的任務的結果進行等待獲取、判斷是否已經完成、取消任務等操作。只有當運算完成的時候結果才能取回,如果運算尚未完成 get 方法將會阻塞。一個 FutureTask 對象可以對調用了 Callable 和 Runnable 的對象進行包裝,由於 FutureTask 也是Runnable 接口的實現類,所以 FutureTask 也可以放入線程池中。

23. 線程的狀態

24. Java 中用到的線程調度算法是什么?

25. 線程的調度策略

26. 什么是線程調度器(Thread Scheduler)和時間分片(Time Slicing )?

27. 請說出與線程同步以及線程調度相關的方法。

28. sleep() 和 wait() 有什么區別?

29. 你是如何調用 wait() 方法的?使用 if 塊還是循環?為什么?

30. 為什么線程通信的方法 wait(), notify()和 notifyAll()被定義在 Object 類里?

31. 為什么 wait(), notify()和 notifyAll()必須在同步方法或者同步塊中被調用?

32. Thread 類中的 yield 方法有什么作用?

33. 為什么 Thread 類的 sleep()和 yield ()方法是靜態的?

34. 線程的 sleep()方法和 yield()方法有什么區別?

35. 如何停止一個正在運行的線程?

36. Java 中 interrupted 和 isInterrupted 方法的區別?

37. 什么是阻塞式方法?

38. Java 中你怎樣喚醒一個阻塞的線程?

39. notify() 和 notifyAll() 有什么區別?

40. 如何在兩個線程間共享數據?

41. Java 如何實現多線程之間的通訊和協作?

42. 同步方法和同步塊,哪個是更好的選擇?

43. 什么是線程同步和線程互斥,有哪幾種實現方式?

44. 在監視器(Monitor)內部,是如何做線程同步的?程序應該做哪種級別的同步?

45. 如果你提交任務時,線程池隊列已滿,這時會發生什么

46. 什么叫線程安全?servlet 是線程安全嗎?

47. 在 Java 程序中怎么保證多線程的運行安全?

48. 你對線程優先級的理解是什么?

49. 線程類的構造方法、靜態塊是被哪個線程調用的

50. Java 中怎么獲取一份線程 dump 文件?你如何在 Java 中獲取線程堆棧?

  • Dump文件是進程的內存鏡像。可以把程序的執行狀態通過調試器保存到dump文件中。
  • 在 Linux 下,你可以通過命令 kill -3 PID (Java 進程的進程 ID)來獲取 Java應用的 dump 文件。
  • 在 Windows 下,你可以按下 Ctrl + Break 來獲取。這樣 JVM 就會將線程的 dump 文件打印到標准輸出或錯誤文件中,它可能打印在控制台或者日志文件中,具體位置依賴應用的配置。

51. 一個線程運行時發生異常會怎樣?

  • 如果異常沒有被捕獲該線程將會停止執行。Thread.UncaughtExceptionHandler是用於處理未捕獲異常造成線程突然中斷情況的一個內嵌接口。當一個未捕獲異常將造成線程中斷的時候,JVM會使用 Thread.getUncaughtExceptionHandler()來查詢線程的 UncaughtExceptionHandler 並將線程和異常作為參數傳遞給 handler 的 uncaughtException()方法進行處理。

52. Java 線程數過多會造成什么異常?

53. 多線程的常用方法

二、並發理論

1. Java中垃圾回收有什么目的?什么時候進行垃圾回收?

  • 垃圾回收是在內存中存在沒有引用的對象或超過作用域的對象時進行的。
  • 垃圾回收的目的是識別並且丟棄應用不再使用的對象來釋放和重用資源。

2. 線程之間如何通信及線程之間如何同步

  • 在並發編程中,我們需要處理兩個關鍵問題:線程之間如何通信及線程之間如何同步。通信是指線程之間以如何來交換信息。一般線程之間的通信機制有兩種:共享內存和消息傳遞。
  • Java的並發采用的是共享內存模型,Java線程之間的通信總是隱式進行,整個通信過程對程序員完全透明。如果編寫多線程程序的Java程序員不理解隱式進行的線程之間通信的工作機制,很可能會遇到各種奇怪的內存可見性問題。

3. Java內存模型

  • 共享內存模型指的就是Java內存模型(簡稱JMM),JMM決定一個線程對共享變量的寫入時,能對另一個線程可見。從抽象的角度來看,JMM定義了線程和主內存之間的抽象關系:線程之間的共享變量存儲在主內存(main memory)中,每個線程都有一個私有的本地內存(local memory),本地內存中存儲了該線程以讀/寫共享變量的副本。本地內存是JMM的一個抽象概念,並不真實存在。它涵蓋了緩存,寫緩沖區,寄存器以及其他的硬件和編譯器優化。

4. 如果對象的引用被置為null,垃圾收集器是否會立即釋放對象占用的內存?

  • 不會,在下一個垃圾回調周期中,這個對象將是被可回收的。
  • 也就是說並不會立即被垃圾收集器立刻回收,而是在下一次垃圾回收時才會釋放其占用的內存。

5. finalize()方法什么時候被調用?析構函數(finalization)的目的是什么?

6. 什么是重排序

7. 重排序實際執行的指令步驟

8. 重排序遵守的規則

9. as-if-serial規則和happens-before規則的區別

10. 並發關鍵字 synchronized ?

11. 說說自己是怎么使用 synchronized 關鍵字,在項目中用到了嗎

12. 單例模式了解嗎?給我解釋一下雙重檢驗鎖方式實現單例模式!”

13. 說一下 synchronized 底層實現原理?

14. synchronized可重入的原理

15. 什么是自旋

16. 多線程中 synchronized 鎖升級的原理是什么?

17. 線程 B 怎么知道線程 A 修改了變量

  • (1)volatile 修飾變量
  • (2)synchronized 修飾修改變量的方法
  • (3)wait/notify
  • (4)while 輪詢

18. 當一個線程進入一個對象的 synchronized 方法 A 之后,其它線程是否可進入此對象的synchronized 方法 B?

19. synchronized、volatile、CAS 比較

  • (1)synchronized 是悲觀鎖,屬於搶占式,會引起其他線程阻塞。
  • (2)volatile 提供多線程共享變量可見性和禁止指令重排序優化。
  • (3)CAS 是基於沖突檢測的樂觀鎖(非阻塞)

20. synchronized 和 Lock 有什么區別?

  • 首先synchronized是Java內置關鍵字,在JVM層面,Lock是個Java類;
  • synchronized 可以給類、方法、代碼塊加鎖;而 lock 只能給代碼塊加鎖。
  • synchronized 不需要手動獲取鎖和釋放鎖,使用簡單,發生異常會自動釋放鎖,不會造成死鎖; 而 lock 需要自己加鎖和釋放鎖,如果使用不當沒有 unLock()去釋放鎖就會造成死鎖。
  • 通過 Lock 可以知道有沒有成功獲取鎖,而 synchronized 卻無法辦到。

21. synchronized 和 ReentrantLock 區別是什么?

22. volatile 關鍵字的作用

23. Java 中能創建 volatile 數組嗎?

24. volatile 變量和 atomic 變量有什么不同?

25. volatile 能使得一個非原子操作變成原子操作嗎?

26. synchronized 和 volatile 的區別是什么?

27. final不可變對象,它對寫並發應用有什么幫助?

28. Lock 接口和synchronized 對比同步它有什么優勢?

29. 樂觀鎖和悲觀鎖的理解及如何實現,有哪些實現方式?

30. 什么是 CAS

31. CAS 的會產生什么問題?

32. 什么是原子類

33. 原子類的常用類

  • AtomicBoolean
  • AtomicInteger
  • AtomicLong
  • AtomicReference

34. 說一下 Atomic的原理?

Atomic包中的類基本的特性就是在多線程環境下,當有多個線程同時對單個(包括基本類型及引用類型)變量進行操作時,具有排他性,即當多個線程同時對該變量的值進行更新時,僅有一個線程能成功,而未成功的線程可以向自旋鎖一樣,繼續嘗試,一直等到執行成功。

35. 死鎖與活鎖的區別,死鎖與飢餓的區別?

三、線程池

1. 什么是線程池?

2. 線程池作用?

3. 線程池有什么優點?

4. 什么是ThreadPoolExecutor?

5. 什么是Executors?

6. 線程池四種創建方式?

7. 在 Java 中 Executor 和 Executors 的區別?

8. 四種構建線程池的區別及特點?

9. 線程池都有哪些狀態?

10. 線程池中 submit() 和 execute() 方法有什么區別?

11. 什么是線程組,為什么在 Java 中不推薦使用?

12. ThreadPoolExecutor飽和策略有哪些?

13. 如何自定義線程線程池?

14. 線程池的執行原理?

15. 如何合理分配線程池大小?

四、並發容器

1. 你經常使用什么並發容器,為什么?

  • 答:Vector、ConcurrentHashMap、HasTable
  • 一般軟件開發中容器用的最多的就是HashMap、ArrayList,LinkedList ,等等
  • 但是在多線程開發中就不能亂用容器,如果使用了未加鎖(非同步)的的集合,你的數據就會非常的混亂。由此在多線程開發中需要使用的容器必須是加鎖(同步)的容器。

2. 什么是Vector

3. ArrayList和Vector有什么不同之處?

4. 為什么HashTable是線程安全的?

5. 用過ConcurrentHashMap,講一下他和HashTable的不同之處?

6. Collections.synchronized * 是什么?

7. Java 中 ConcurrentHashMap 的並發度是什么?

8. 什么是並發容器的實現?

9. Java 中的同步集合與並發集合有什么區別?

10. SynchronizedMap 和 ConcurrentHashMap 有什么區別?

11. CopyOnWriteArrayList 是什么?

12. CopyOnWriteArrayList 的使用場景?

合適讀多寫少的場景。

13. CopyOnWriteArrayList 的缺點?

14. CopyOnWriteArrayList 的設計思想?

五、並發隊列

1. 什么是並發隊列:

  • 消息隊列很多人知道:消息隊列是分布式系統中重要的組件,是系統與系統直接的通信
  • 並發隊列是什么:並發隊列多個線程以有次序共享數據的重要組件

2. 並發隊列和並發集合的區別:

  • 隊列遵循“先進先出”的規則,可以想象成排隊檢票,隊列一般用來解決大數據量采集處理和顯示 的。
  • 並發集合就是在多個線程中共享數據的

3. 怎么判斷並發隊列是阻塞隊列還是非阻塞隊列

在並發隊列上JDK提供了Queue接口,一個是以Queue接口下的BlockingQueue接口為代表的阻塞 隊列,另一個是高性能(無堵塞)隊列。

4. 阻塞隊列和非阻塞隊列區別

  • 當隊列阻塞隊列為空的時,從隊列中獲取元素的操作將會被阻塞。
  • 或者當阻塞隊列是滿時,往隊列里添加元素的操作會被阻塞。
  • 或者試圖從空的阻塞隊列中獲取元素的線程將會被阻塞,直到其他的線程往空的隊列插入新的元素。
  • 試圖往已滿的阻塞隊列中添加新元素的線程同樣也會被阻塞,直到其他的線程使隊列重新變得空閑起來

5. 常用並發列隊的介紹:

並發隊列的常用方法

六、並發工具類

1. 常用的並發工具類有哪些?

最后

小編分享的文章到這里就結束了,整理不易,歡迎大家一起交流。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM