成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java多線程八股文背誦版V0.2

開發 后端
java內存模型定義了程序中各種變量的訪問規則。其規定所有變量都存儲在主內存,線程均有自己的工作內存。工作內存中保存被該線程使用的變量的主內存副本,線程對變量的所有操作都必須在工作空間進行,不能直接讀寫主內存數據。

[[417056]]

本文轉載自微信公眾號「后端技術小牛說」,作者后端技術小牛說。轉載本文請聯系后端技術小牛說公眾號。

寫在最前面

最近有收到讀者的一些反饋,感謝了我開發了網站interviewtop.top,對他們面試產生了巨大幫助,更有讀者給我發了小紅包贊助我。當然啦,我也知道大家還是以學生群體為主,紅包和贊助免了哈!

我之前還是學生身份,分別租了阿里云騰訊云等等云服務器的9.9元學生套餐,利用各個廠的學生福利云服務器負載均衡做服務器后端,這幾個月,由于已經成為社會人了,當然沒這點福利了(9.9同等配置社會人現在得近200,所以還在上學的同學有需求這個羊毛可以薅一把)。而且隨著大家使用頻率的增高,配置要求當然也不一定打的住了。

除此之外,interviewtop網站也需要大家的幫助和支持!如果大家有面經,希望大家能貢獻一下:

在全部和對應題庫下點擊搜索

搜索自己的面試題

點擊這題我面試見過,貢獻一下自己的面試經歷

如果有些題題庫沒收錄,歡迎大家添加小牛微信,小牛后臺更新上!

簡述java內存模型(JMM)

java內存模型定義了程序中各種變量的訪問規則。其規定所有變量都存儲在主內存,線程均有自己的工作內存。工作內存中保存被該線程使用的變量的主內存副本,線程對變量的所有操作都必須在工作空間進行,不能直接讀寫主內存數據。操作完成后,線程的工作內存通過緩存一致性協議將操作完的數據刷回主存。

簡述as-if-serial

編譯器等會對原始的程序進行指令重排序和優化。但不管怎么重排序,其結果和用戶原始程序輸出預定結果一致。

簡述happens-before八大原則

程序次序規則:一個線程內寫在前面的操作先行發生于后面的。

鎖定規則:unlock 操作先行發生于后面對同一個鎖的 lock 操作。

volatile 規則:對 volatile 變量的寫操作先行發生于后面的讀操作。

線程啟動規則:線程的 start 方法先行發生于線程的每個動作。

線程中斷規則:對線程interrupt()方法的調用先行發生于被中斷線程的代碼檢測到中斷事件的發生。

線程終止規則:線程中所有操作先行發生于對線程的終止檢測。

對象終結規則:對象的初始化先行發生于 finalize 方法。

傳遞性規則:如果操作 A 先行發生于操作 B,操作 B 先行發生于操作 C,那么操作 A 先行發生于操作 C

as-if-serial 和 happens-before 的區別

as-if-serial 保證單線程程序的執行結果不變,happens-before 保證正確同步的多線程程序的執行結果不變。

簡述原子性操作

一個操作或者多個操作,要么全部執行并且執行的過程不會被任何因素打斷,要么就都不執行,這就是原子性操作。

簡述線程的可見性

可見性指當一個線程修改了共享變量時,其他線程能夠立即得知修改。volatile,synchronized,final都能保證可見性。

簡述有序性

即雖然多線程存在并發和指令優化等操作,在本線程內觀察該線程的所有執行操作是有序的。

簡述java中volatile關鍵字作用

保證變量對所有線程的可見性。當一條線程修改了變量值,新值對于其他線程來說是立即可以得知的。

禁止指令重排序優化。使用 volatile 變量進行寫操作,匯編指令帶有 lock 前綴,相當于一個內存屏障,編譯器不會將后面的指令重排到內存屏障之前。

java線程的實現方式

  • 實現Runnable接口
  • 繼承Thread類。
  • 實現Callable接口

簡述java線程的狀態

線程狀態有New, RUNNABLE, BLOCK, WAITING, TIMED_WAITING, THERMINATED NEW:新建狀態,線程被創建且未啟動,此時還未調用 start 方法。

RUNNABLE: 運行狀態。其表示線程正在JVM中執行,但是這個執行,不一定真的在跑,也可能在排隊等CPU。

BLOCKED:阻塞狀態。線程等待獲取鎖,鎖還沒獲得。

WAITING: 等待狀態。線程內run方法運行完語句Object.wait()/Thread.join()進入該狀態。

TIMED_WAITING:限期等待。在一定時間之后跳出狀態。調用Thread.sleep(long) Object.wait(long) Thread.join(long)進入狀態。其中這些參數代表等待的時間。

TERMINATED:結束狀態。線程調用完run方法進入該狀態。

簡述線程通信的方式

  1. volatile 關鍵詞修飾變量,保證所有線程對變量訪問的可見性。
  2. synchronized關鍵詞。確保多個線程在同一時刻只能有一個處于方法或同步塊中。
  3. wait/notify方法
  4. IO通信

簡述線程池

沒有線程池的情況下,多次創建,銷毀線程開銷比較大。如果在開辟的線程執行完當前任務后執行接下來任務,復用已創建的線程,降低開銷、控制最大并發數。

線程池創建線程時,會將線程封裝成工作線程 Worker,Worker 在執行完任務后還會循環獲取工作隊列中的任務來執行。

將任務派發給線程池時,會出現以下幾種情況

核心線程池未滿,創建一個新的線程執行任務。

如果核心線程池已滿,工作隊列未滿,將線程存儲在工作隊列。

如果工作隊列已滿,線程數小于最大線程數就創建一個新線程處理任務。

如果超過大小線程數,按照拒絕策略來處理任務。

線程池參數

  1. corePoolSize:常駐核心線程數。超過該值后如果線程空閑會被銷毀。
  2. maximumPoolSize:線程池能夠容納同時執行的線程最大數。
  3. keepAliveTime:線程空閑時間,線程空閑時間達到該值后會被銷毀,直到只剩下 corePoolSize 個線程為止,避免浪費內存資源。
  4. workQueue:工作隊列。
  5. threadFactory:線程工廠,用來生產一組相同任務的線程。
  6. handler:拒絕策略。有以下幾種拒絕策略:
  • AbortPolicy:丟棄任務并拋出異常
  • CallerRunsPolicy:重新嘗試提交該任務
  • DiscardOldestPolicy 拋棄隊列里等待最久的任務并把當前任務加入隊列
  • DiscardPolicy 表示直接拋棄當前任務但不拋出異常。

線程池創建方法

newFixedThreadPool,創建固定大小的線程池。

newSingleThreadExecutor,使用單線程線程池。

newCachedThreadPool,maximumPoolSize 設置為 Integer 最大值,工作完成后會回收工作線程

newScheduledThreadPool:支持定期及周期性任務執行,不回收工作線程。

newWorkStealingPool:一個擁有多個任務隊列的線程池。

簡述Executor框架

Executor框架目的是將任務提交和任務如何運行分離開來的機制。用戶不再需要從代碼層考慮設計任務的提交運行,只需要調用Executor框架實現類的Execute方法就可以提交任務。產生線程池的函數ThreadPoolExecutor也是Executor的具體實現類。

簡述Executor的繼承關系

  • Executor:一個接口,其定義了一個接收Runnable對象的方法executor,該方法接收一個Runable實例執行這個任務。
  • ExecutorService:Executor的子類接口,其定義了一個接收Callable對象的方法,返回 Future 對象,同時提供execute方法。
  • ScheduledExecutorService:ExecutorService的子類接口,支持定期執行任務。
  • AbstractExecutorService:抽象類,提供 ExecutorService 執行方法的默認實現。
  • Executors:實現ExecutorService接口的靜態工廠類,提供了一系列工廠方法用于創建線程池。
  • ThreadPoolExecutor:繼承AbstractExecutorService,用于創建線程池。
  • ForkJoinPool: 繼承AbstractExecutorService,Fork 將大任務分叉為多個小任務,然后讓小任務執行,Join 是獲得小任務的結果,類似于map reduce。
  • ThreadPoolExecutor:繼承ThreadPoolExecutor,實現ScheduledExecutorService,用于創建帶定時任務的線程池。

簡述線程池的狀態

  • Running:能接受新提交的任務,也可以處理阻塞隊列的任務。
  • Shutdown:不再接受新提交的任務,但可以處理存量任務,線程池處于running時調用shutdown方法,會進入該狀態。
  • Stop:不接受新任務,不處理存量任務,調用shutdownnow進入該狀態。
  • Tidying:所有任務已經終止了,worker_count(有效線程數)為0。
  • Terminated:線程池徹底終止。在tidying模式下調用terminated方法會進入該狀態。

簡述阻塞隊列

阻塞隊列是生產者消費者的實現具體組件之一。當阻塞隊列為空時,從隊列中獲取元素的操作將會被阻塞,當阻塞隊列滿了,往隊列添加元素的操作將會被阻塞。具體實現有:

  • ArrayBlockingQueue:底層是由數組組成的有界阻塞隊列。
  • LinkedBlockingQueue:底層是由鏈表組成的有界阻塞隊列。
  • PriorityBlockingQueue:阻塞優先隊列。
  • DelayQueue:創建元素時可以指定多久才能從隊列中獲取當前元素
  • SynchronousQueue:不存儲元素的阻塞隊列,每一個存儲必須等待一個取出操作
  • LinkedTransferQueue:與LinkedBlockingQueue相比多一個transfer方法,即如果當前有消費者正等待接收元素,可以把生產者傳入的元素立刻傳輸給消費者。
  • LinkedBlockingDeque:雙向阻塞隊列。

談一談ThreadLocal

ThreadLocal 是線程共享變量。ThreadLoacl 有一個靜態內部類 ThreadLocalMap,其 Key 是 ThreadLocal 對象,值是 Entry 對象,ThreadLocalMap是每個線程私有的。

  • set 給ThreadLocalMap設置值。
  • get 獲取ThreadLocalMap。
  • remove 刪除ThreadLocalMap類型的對象。

存在的問題

  1. 對于線程池,由于線程池會重用 Thread 對象,因此與 Thread 綁定的 ThreadLocal 也會被重用,造成一系列問題。
  2. 內存泄漏。由于 ThreadLocal 是弱引用,但 Entry 的 value 是強引用,因此當 ThreadLocal 被垃圾回收后,value 依舊不會被釋放,產生內存泄漏。

聊聊你對java并發包下unsafe類的理解

對于 Java 語言,沒有直接的指針組件,一般也不能使用偏移量對某塊內存進行操作。這些操作相對來講是安全(safe)的。

Java 有個類叫 Unsafe 類,這個類類使 Java 擁有了像 C 語言的指針一樣操作內存空間的能力,同時也帶來了指針的問題。這個類可以說是 Java 并發開發的基礎。

JAVA中的樂觀鎖與CAS算法

對于樂觀鎖,開發者認為數據發送時發生并發沖突的概率不大,所以讀操作前不上鎖。

到了寫操作時才會進行判斷,數據在此期間是否被其他線程修改。如果發生修改,那就返回寫入失敗;如果沒有被修改,那就執行修改操作,返回修改成功。

樂觀鎖一般都采用 Compare And Swap(CAS)算法進行實現。顧名思義,該算法涉及到了兩個操作,比較(Compare)和交換(Swap)。

CAS 算法的思路如下:

  1. 該算法認為不同線程對變量的操作時產生競爭的情況比較少。
  2. 該算法的核心是對當前讀取變量值 E 和內存中的變量舊值 V 進行比較。
  3. 如果相等,就代表其他線程沒有對該變量進行修改,就將變量值更新為新值 N。
  4. 如果不等,就認為在讀取值 E 到比較階段,有其他線程對變量進行過修改,不進行任何操作。

ABA問題及解決方法簡述

CAS 算法是基于值來做比較的,如果當前有兩個線程,一個線程將變量值從 A 改為 B ,再由 B 改回為 A ,當前線程開始執行 CAS 算法時,就很容易認為值沒有變化,誤認為讀取數據到執行 CAS 算法的期間,沒有線程修改過數據。

juc 包提供了一個 AtomicStampedReference,即在原始的版本下加入版本號戳,解決 ABA 問題。

簡述常見的Atomic類

在很多時候,我們需要的僅僅是一個簡單的、高效的、線程安全的++或者--方案,使用synchronized關鍵字和lock固然可以實現,但代價比較大,此時用原子類更加方便。基本數據類型的原子類有:

  • AtomicInteger 原子更新整形
  • AtomicLong 原子更新長整型
  • AtomicBoolean 原子更新布爾類型

Atomic數組類型有:

  • AtomicIntegerArray 原子更新整形數組里的元素
  • AtomicLongArray 原子更新長整型數組里的元素
  • AtomicReferenceArray 原子更新引用類型數組里的元素。

Atomic引用類型有

  • AtomicReference 原子更新引用類型
  • AtomicMarkableReference 原子更新帶有標記位的引用類型,可以綁定一個 boolean 標記
  • AtomicStampedReference 原子更新帶有版本號的引用類型

FieldUpdater類型:

  • AtomicIntegerFieldUpdater 原子更新整形字段的更新器
  • AtomicLongFieldUpdater 原子更新長整形字段的更新器
  • AtomicReferenceFieldUpdater 原子更新引用類型字段的更新器

簡述Atomic類基本實現原理

以AtomicIntger 為例:方法getAndIncrement:以原子方式將當前的值加1,具體實現為:

  1. 在 for 死循環中取得 AtomicInteger 里存儲的數值
  2. 對 AtomicInteger 當前的值加 1
  3. 調用 compareAndSet 方法進行原子更新
  4. 先檢查當前數值是否等于 expect
  5. 如果等于則說明當前值沒有被其他線程修改,則將值更新為 next,
  6. 如果不是會更新失敗返回 false,程序會進入 for 循環重新進行 compareAndSet 操作。

簡述CountDownLatch

countDownLatch這個類使一個線程等待其他線程各自執行完畢后再執行。是通過一個計數器來實現的,計數器的初始值是線程的數量。每當一個線程執行完畢后,調用countDown方法,計數器的值就減1,當計數器的值為0時,表示所有線程都執行完畢,然后在等待的線程就可以恢復工作了。只能一次性使用,不能reset。

簡述CyclicBarrier

CyclicBarrier 主要功能和countDownLatch類似,也是通過一個計數器,使一個線程等待其他線程各自執行完畢后再執行。但是其可以重復使用(reset)。

簡述Semaphore

Semaphore即信號量。Semaphore 的構造方法參數接收一個 int 值,設置一個計數器,表示可用的許可數量即最大并發數。使用 acquire 方法獲得一個許可證,計數器減一,使用 release 方法歸還許可,計數器加一。如果此時計數器值為0,線程進入休眠。

簡述Exchanger

Exchanger類可用于兩個線程之間交換信息。可簡單地將Exchanger對象理解為一個包含兩個格子的容器,通過exchanger方法可以向兩個格子中填充信息。線程通過exchange 方法交換數據,第一個線程執行 exchange 方法后會阻塞等待第二個線程執行該方法。當兩個線程都到達同步點時這兩個線程就可以交換數據當兩個格子中的均被填充時,該對象會自動將兩個格子的信息交換,然后返回給線程,從而實現兩個線程的信息交換。

簡述ConcurrentHashMap

JDK7采用鎖分段技術。首先將數據分成 Segment 數據段,然后給每一個數據段配一把鎖,當一個線程占用鎖訪問其中一個段的數據時,其他段的數據也能被其他線程訪問。

get 除讀到空值不需要加鎖。該方法先經過一次再散列,再用這個散列值通過散列運算定位到 Segment,最后通過散列算法定位到元素。put 須加鎖,首先定位到 Segment,然后進行插入操作,第一步判斷是否需要對 Segment 里的 HashEntry 數組進行擴容,第二步定位添加元素的位置,然后將其放入數組。

JDK8的改進

  1. 取消分段鎖機制,采用CAS算法進行值的設置,如果CAS失敗再使用 synchronized 加鎖添加元素
  2. 引入紅黑樹結構,當某個槽內的元素個數超過8且 Node數組 容量大于 64 時,鏈表轉為紅黑樹。
  3. 使用了更加優化的方式統計集合內的元素數量。

Synchronized底層實現原理

Java 對象底層都關聯一個的 monitor,使用 synchronized 時 JVM 會根據使用環境找到對象的 monitor,根據 monitor 的狀態進行加解鎖的判斷。如果成功加鎖就成為該 monitor 的唯一持有者,monitor 在被釋放前不能再被其他線程獲取。

synchronized在JVM編譯后會產生monitorenter 和 monitorexit 這兩個字節碼指令,獲取和釋放 monitor。這兩個字節碼指令都需要一個引用類型的參數指明要鎖定和解鎖的對象,對于同步普通方法,鎖是當前實例對象;對于靜態同步方法,鎖是當前類的 Class 對象;對于同步方法塊,鎖是 synchronized 括號里的對象。

執行 monitorenter 指令時,首先嘗試獲取對象鎖。如果這個對象沒有被鎖定,或當前線程已經持有鎖,就把鎖的計數器加 1,執行 monitorexit 指令時會將鎖計數器減 1。一旦計數器為 0 鎖隨即就被釋放。

Synchronized關鍵詞使用方法

  1. 直接修飾某個實例方法
  2. 直接修飾某個靜態方法
  3. 修飾代碼塊

簡述java偏向鎖

JDK 1.6 中提出了偏向鎖的概念。該鎖提出的原因是,開發者發現多數情況下鎖并不存在競爭,一把鎖往往是由同一個線程獲得的。偏向鎖并不會主動釋放,這樣每次偏向鎖進入的時候都會判斷該資源是否是偏向自己的,如果是偏向自己的則不需要進行額外的操作,直接可以進入同步操作。

其申請流程為:

  1. 首先需要判斷對象的 Mark Word 是否屬于偏向模式,如果不屬于,那就進入輕量級鎖判斷邏輯。否則繼續下一步判斷;
  2. 判斷目前請求鎖的線程 ID 是否和偏向鎖本身記錄的線程 ID 一致。如果一致,繼續下一步的判斷,如果不一致,跳轉到步驟4;
  3. 判斷是否需要重偏向。如果不用的話,直接獲得偏向鎖;
  4. 利用 CAS 算法將對象的 Mark Word 進行更改,使線程 ID 部分換成本線程 ID。如果更換成功,則重偏向完成,獲得偏向鎖。如果失敗,則說明有多線程競爭,升級為輕量級鎖。

簡述輕量級鎖

輕量級鎖是為了在沒有競爭的前提下減少重量級鎖出現并導致的性能消耗。

其申請流程為:

  1. 如果同步對象沒有被鎖定,虛擬機將在當前線程的棧幀中建立一個鎖記錄空間,存儲鎖對象目前 Mark Word 的拷貝。
  2. 虛擬機使用 CAS 嘗試把對象的 Mark Word 更新為指向鎖記錄的指針
  3. 如果更新成功即代表該線程擁有了鎖,鎖標志位將轉變為 00,表示處于輕量級鎖定狀態。
  4. 如果更新失敗就意味著至少存在一條線程與當前線程競爭。虛擬機檢查對象的 Mark Word 是否指向當前線程的棧幀
  5. 如果指向當前線程的棧幀,說明當前線程已經擁有了鎖,直接進入同步塊繼續執行
  6. 如果不是則說明鎖對象已經被其他線程搶占。
  7. 如果出現兩條以上線程爭用同一個鎖,輕量級鎖就不再有效,將膨脹為重量級鎖,鎖標志狀態變為 10,此時Mark Word 存儲的就是指向重量級鎖的指針,后面等待鎖的線程也必須阻塞。

簡述鎖優化策略

即自適應自旋、鎖消除、鎖粗化、鎖升級等策略偏。

簡述java的自旋鎖

線程獲取鎖失敗后,可以采用這樣的策略,可以不放棄 CPU ,不停的重試內重試,這種操作也稱為自旋鎖。

簡述自適應自旋鎖

自適應自旋鎖自旋次數不再人為設定,通常由前一次在同一個鎖上的自旋時間及鎖的擁有者的狀態決定。

簡述鎖粗化

鎖粗化的思想就是擴大加鎖范圍,避免反復的加鎖和解鎖。

簡述鎖消除

鎖消除是一種更為徹底的優化,在編譯時,java編譯器對運行上下文進行掃描,去除不可能存在共享資源競爭的鎖。

簡述Lock與ReentrantLock

Lock 接是 java并發包的頂層接口。

可重入鎖 ReentrantLock 是 Lock 最常見的實現,與 synchronized 一樣可重入。ReentrantLock 在默認情況下是非公平的,可以通過構造方法指定公平鎖。一旦使用了公平鎖,性能會下降。

簡述AQS

AQS(AbstractQuenedSynchronizer)抽象的隊列式同步器。AQS是將每一條請求共享資源的線程封裝成一個鎖隊列的一個結點(Node),來實現鎖的分配。AQS是用來構建鎖或其他同步組件的基礎框架,它使用一個 volatile int state 變量作為共享資源,如果線程獲取資源失敗,則進入同步隊列等待;如果獲取成功就執行臨界區代碼,釋放資源時會通知同步隊列中的等待線程。

子類通過繼承同步器并實現它的抽象方法getState、setState 和 compareAndSetState對同步狀態進行更改。

AQS獲取獨占鎖/釋放獨占鎖原理

獲取:(acquire)

  1. 調用 tryAcquire 方法安全地獲取線程同步狀態,獲取失敗的線程會被構造同步節點并通過 addWaiter 方法加入到同步隊列的尾部,在隊列中自旋。
  2. 調用 acquireQueued 方法使得該節點以死循環的方式獲取同步狀態,如果獲取不到則阻塞。

釋放:(release)

  1. 調用 tryRelease 方法釋放同步狀態
  2. 調用 unparkSuccessor 方法喚醒頭節點的后繼節點,使后繼節點重新嘗試獲取同步狀態。

AQS獲取共享鎖/釋放共享鎖原理

獲取鎖(acquireShared)

調用 tryAcquireShared 方法嘗試獲取同步狀態,返回值不小于 0 表示能獲取同步狀態。

釋放(releaseShared)

釋放,并喚醒后續處于等待狀態的節點。

線程池類型

  1. newCachedThreadPool 可緩存線程池,可設置最小線程數和最大線程數,線程空閑1分鐘后自動銷毀。
  2. newFixedThreadPool 指定工作線程數量線程池。
  3. newSingleThreadExecutor 單線程Executor。
  4. newScheduleThreadPool 支持定時任務的指定工作線程數量線程池。
  5. newSingleThreadScheduledExecutor 支持定時任務的單線程Executor。

 

責任編輯:武曉燕 來源: 后端技術小牛說
相關推薦

2021-04-14 10:02:59

網絡八股文協議

2021-05-20 11:43:57

操作系統硬件軟件

2021-10-21 14:43:23

Java 語言 Java 基礎

2021-10-26 14:40:03

MySQL SQL 語句數據庫

2021-11-04 14:32:17

Spring 面試作用域

2021-07-26 14:59:23

面試Redis內存數據庫

2021-09-07 14:46:42

面試網絡HTTP 協議

2023-11-28 18:09:49

Java多態

2022-09-03 11:36:11

Python文件網絡

2021-10-26 17:05:55

Redis字符串復雜度

2024-10-12 09:26:32

線程池系統核心線程

2021-08-01 22:59:43

Object八股文quals

2024-02-23 19:17:12

構造函數C++開發

2022-01-04 08:54:32

Redis數據庫數據類型

2021-05-06 07:27:57

面試任務調度器

2023-12-12 13:38:00

Java異步編程

2023-11-29 17:28:07

2022-05-27 14:43:45

JVM字節碼指令

2022-05-19 08:41:09

JVM虛擬機架構

2023-01-13 18:04:03

面試題消息中間件
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美一区二区三区在线播放 | 国产一区二区三区四区五区3d | 天天插天天射天天干 | 日本视频在线播放 | 亚洲精品一区二区在线观看 | 成人久久久 | 亚洲一区二区三区四区五区中文 | 国产成人在线一区二区 | 欧美视频在线一区 | 综合久 | 毛片一区二区三区 | 色综合色综合色综合 | 日本久久精品 | 成人福利 | 亚洲精品视频二区 | 无码一区二区三区视频 | 久久国产精品无码网站 | 免费成人在线网站 | 亚洲欧美激情四射 | 97超级碰碰 | 亚洲成人一区二区 | 亚洲性人人天天夜夜摸 | 国产精品一区二区不卡 | 欧洲亚洲视频 | 色一级片| 二区中文| 欧美性乱 | 久久精品日| 日韩欧美专区 | 精品乱码一区二区三四区视频 | 精品国产乱码久久久久久丨区2区 | www.久久精品视频 | 成人在线免费视频 | 久久亚洲精品久久国产一区二区 | 精品在线一区 | 激情五月综合网 | av中文字幕在线观看 | 久草青青草 | 欧美极品一区二区 | 亚洲精品免费在线观看 | 欧美日本一区二区 |