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

Java 線程的狀態(tài)及轉(zhuǎn)換

開發(fā) 后端
將弱化 threadStatus 這個(gè)整數(shù)值了,就直接說(shuō)改變了其線程狀態(tài),大家知道其實(shí)就只是改變了 threadStatus 的值而已。

低并發(fā)編程

戰(zhàn)略上藐視技術(shù),戰(zhàn)術(shù)上重視技術(shù)

閃客:小宇你怎么了,我看你臉色很不好呀。

小宇:今天去面試了,面試官問(wèn)我 Java 線程的狀態(tài)及其轉(zhuǎn)化。

閃客:哦哦,很常見的面試題呀,不是有一張狀態(tài)流轉(zhuǎn)圖嘛。

小宇:我知道,可是我每次面試的時(shí)候,腦子里記過(guò)的流轉(zhuǎn)圖就變成這樣了。


閃客:哈哈哈。

小宇:你還笑,氣死我了,你能不能給我講講這些亂七八糟的狀態(tài)呀。

閃客:沒問(wèn)題,還是老規(guī)矩,你先把所有狀態(tài)都忘掉,聽我從頭道來(lái)!

小宇:好滴。

線程狀態(tài)的實(shí)質(zhì)

首先你得明白,當(dāng)我們說(shuō)一個(gè)線程的狀態(tài)時(shí),說(shuō)的是什么?

沒錯(cuò),就是一個(gè)變量的值而已。

哪個(gè)變量?

Thread 類中的一個(gè)變量,叫

private volatile int threadStatus = 0;

這個(gè)值是個(gè)整數(shù),不方便理解,可以通過(guò)映射關(guān)系(VM.toThreadState),轉(zhuǎn)換成一個(gè)枚舉類。

public enum State {

NEW,

RUNNABLE,

BLOCKED,

WAITING,

TIMED_WAITING,

TERMINATED;

}

所以,我們就盯著 threadStatus 這個(gè)值的變化就好了。

就是這么簡(jiǎn)單。

NEW

現(xiàn)在我們還沒有任何 Thread 類的對(duì)象呢,也就不存在線程狀態(tài)一說(shuō)。

一切的起點(diǎn),要從把一個(gè) Thread 類的對(duì)象創(chuàng)建出來(lái),開始說(shuō)起。

Thread t = new Thread();

當(dāng)然,你后面可以接很多參數(shù)。

Thread t = new Thread(r, "name1");

你也可以 new 一個(gè)繼承了 Thread 類的子類。

Thread t = new MyThread();

你說(shuō)線程池怎么不 new 就可以有線程了呢?人家內(nèi)部也是 new 出來(lái)的。

public class Executors {
static class DefaultThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread t = new Thread();
return t;
}
}
public class Executors {
static class DefaultThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread t = new Thread();
return t;
}
}
public class Executors {
static class DefaultThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread t = new Thread();
return t;
}
}
}

總是,一切的開始,都要調(diào)用 Thread 類的構(gòu)造方法。

而這個(gè)構(gòu)造方法,最終都會(huì)調(diào)用 Thread 類的 init () 方法。

private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) {
this.grout = g;
this.name = name;
tid = nextThreadID();
}

這個(gè) init 方法,僅僅是給該 Thread 類的對(duì)象中的屬性,附上值,除此之外啥也沒干。

它沒有給 theadStatus 再次賦值,所以它的值仍然是其默認(rèn)值。

而這個(gè)值對(duì)應(yīng)的狀態(tài),就是 STATE.NEW,非要翻譯成中文,就叫初始態(tài)吧。

因此說(shuō)了這么多,其實(shí)就分析出了,新建一個(gè) Thread 類的對(duì)象,就是創(chuàng)建了一個(gè)新的線程,此時(shí)這個(gè)線程的狀態(tài),是 NEW(初始態(tài))。

之后的分析,將弱化 threadStatus 這個(gè)整數(shù)值了,就直接說(shuō)改變了其線程狀態(tài),大家知道其實(shí)就只是改變了 threadStatus 的值而已。

RUNNABLE

你說(shuō),剛剛處于 NEW 狀態(tài)的線程,對(duì)應(yīng)操作系統(tǒng)里的什么狀態(tài)呢?

一看你就沒仔細(xì)看我上面的分析。

Thread t = new Thread();

只是做了些表面功夫,在 Java 語(yǔ)言層面將自己的一個(gè)對(duì)象中的屬性附上值罷了,根本沒碰到操作系統(tǒng)級(jí)別的東西呢。

所以這個(gè) NEW 狀態(tài),不論往深了說(shuō)還是往淺了說(shuō),還真就只是個(gè)無(wú)聊的枚舉值而已。

下面,精彩的故事才剛剛開始。

躺在堆內(nèi)存中無(wú)所事事的 Thread 對(duì)象,在調(diào)用了 start () 方法后,才顯現(xiàn)生機(jī)。

t.start();

這個(gè)方法一調(diào)用,那可不得了,最終會(huì)調(diào)用到一個(gè)討厭的 native 方法里。

private native void start0();

看來(lái)改變狀態(tài)就并不是一句 threadStatus = xxx 這么簡(jiǎn)單了,而是有本地方法對(duì)其進(jìn)行了修改。

九曲十八彎跟進(jìn) jvm 源碼之后,調(diào)用到了這個(gè)方法。

hotspot/src/os/linux/vm/os_linux.cpp
pthread_create();

大名鼎鼎的 unix 創(chuàng)建線程的方法,pthread_create。

此時(shí),在操作系統(tǒng)內(nèi)核中,才有了一個(gè)真正的線程,被創(chuàng)建出來(lái)。

而 linux 操作系統(tǒng),是沒有所謂的剛創(chuàng)建但沒啟動(dòng)的線程這種說(shuō)法的,創(chuàng)建即刻開始運(yùn)行。

雖然無(wú)法從源碼發(fā)現(xiàn)線程狀態(tài)的變化,但通過(guò) debug 的方式,我們看到調(diào)用了 Thread.start () 方法后,線程的狀態(tài)變成了 RUNNABLE,運(yùn)行態(tài)。

那我們的狀態(tài)圖又豐富了起來(lái)。


通過(guò)這部分,我們知道如下幾點(diǎn):

1. 在 Java 調(diào)用 start () 后,操作系統(tǒng)中才真正出現(xiàn)了一個(gè)線程,并且立刻運(yùn)行。

2. Java 中的線程,和操作系統(tǒng)內(nèi)核中的線程,是一對(duì)一的關(guān)系。

3. 調(diào)用 start 后,線程狀態(tài)變?yōu)?RUNNABLE,這是由 native 方法里的某部分代碼造成的。

RUNNING 和 READY

CPU 一個(gè)核心,同一時(shí)刻,只能運(yùn)行一個(gè)線程。

具體執(zhí)行哪個(gè)線程,要看操作系統(tǒng) 的調(diào)度機(jī)制。

所以,上面的 RUNNABLE 狀態(tài),準(zhǔn)確說(shuō)是,得到了可以隨時(shí)準(zhǔn)備運(yùn)行的機(jī)會(huì)的狀態(tài)。

而處于這個(gè)狀態(tài)中的線程,也分為了正在 CPU 中運(yùn)行的線程,和一堆處于就緒中等待 CPU 分配時(shí)間片來(lái)運(yùn)行的線程。

處于就緒中的線程,會(huì)存儲(chǔ)在一個(gè)就緒隊(duì)列中,等待著被操作系統(tǒng)的調(diào)度機(jī)制選到,進(jìn)入 CPU 中運(yùn)行。

當(dāng)然,要注意,這里的 RUNNING 和 READY 狀態(tài),是我們自己為了方便描述而造出來(lái)的。

無(wú)論是 Java 語(yǔ)言,還是操作系統(tǒng),都不區(qū)分這兩種狀態(tài),在 Java 中統(tǒng)統(tǒng)叫 RUNNABLE。

TERMINATED

當(dāng)一個(gè)線程執(zhí)行完畢(或者調(diào)用已經(jīng)不建議的 stop 方法),線程的狀態(tài)就變?yōu)?TERMINATED。

此時(shí)這個(gè)線程已經(jīng)無(wú)法死灰復(fù)燃了,如果你此時(shí)再?gòu)?qiáng)行執(zhí)行 start 方法,將會(huì)報(bào)出錯(cuò)誤。

java.lang.IllegalThreadStateException

很簡(jiǎn)單,因?yàn)?start 方法的第一行就是這么直戳了當(dāng)?shù)貙懙摹?/p>

public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
...
}

誒,那如果此時(shí)強(qiáng)行把 threadStatus 改成 0,會(huì)怎么樣呢?你可以試試喲。

BLOCKED

上面把最常見,最簡(jiǎn)單的線程生命周期講完了。

初始 -- 運(yùn)行 -- 終止

沒有發(fā)生任何的障礙。

接下來(lái),就稍稍復(fù)雜一點(diǎn)了,我們讓線程碰到些障礙。

首先創(chuàng)建一個(gè)對(duì)象 lock。

public static final Object lock = new Object();

一個(gè)線程,執(zhí)行一個(gè) sychronized 塊,鎖對(duì)象是 lock,且一直持有這把鎖不放。

new Thread(() - {
synchronized (lock) {
while(true) {}
}
}).start();

另一個(gè)線程,也同樣執(zhí)行一個(gè)鎖對(duì)象為 lock 的 sychronized 塊。

new Thread(() - {
synchronized (lock) {
...
}
}).start();

那么,在進(jìn)入 synchronized 塊時(shí),因?yàn)闊o(wú)法拿到鎖,會(huì)使線程狀態(tài)變?yōu)?BLOCKED。

同樣,對(duì)于 synchronized 方法,也是如此。

當(dāng)該線程獲取到了鎖后,便可以進(jìn)入 synchronized 塊,此時(shí)線程狀態(tài)變?yōu)?RUNNABLE。

因此我們得出如下轉(zhuǎn)換關(guān)系。

當(dāng)然,這只是線程狀態(tài)的改變,線程還發(fā)生了一些實(shí)質(zhì)性的變化。

我們不考慮虛擬機(jī)對(duì) synchronized 的極致優(yōu)化。

當(dāng)進(jìn)入 synchronized 塊或方法,獲取不到鎖時(shí),線程會(huì)進(jìn)入一個(gè)該鎖對(duì)象的同步隊(duì)列。

當(dāng)持有鎖的這個(gè)線程,釋放了鎖之后,會(huì)喚醒該鎖對(duì)象同步隊(duì)列中的所有線程,這些線程會(huì)繼續(xù)嘗試搶鎖。如此往復(fù)。

比如,有一個(gè)鎖對(duì)象 A,線程 1 此時(shí)持有這把鎖。線程 2、3、4 分別嘗試搶這把鎖失敗。


線程 1 釋放鎖,線程 2、3、4 重新變?yōu)?RUNNABLE,繼續(xù)搶鎖,假如此時(shí)線程 3 搶到了鎖。

如此往復(fù)。

WAITING

這部分是最復(fù)雜的,同時(shí)也是面試中考點(diǎn)最多的,將分成三部分講解。聽我說(shuō)完后你會(huì)發(fā)現(xiàn),這三部分有很多相同但地方,不再是孤立的知識(shí)點(diǎn)。

wait/notify

我們?cè)趧倓偟?synchronized 塊中加點(diǎn)東西。

new Thread(() - {
synchronized (lock) {
...
lock.wait();
...
}
}).start();

當(dāng)這個(gè) lock.wait () 方法一調(diào)用,會(huì)發(fā)生三件事。

1. 釋放鎖對(duì)象 lock(隱含著必須先獲取到這個(gè)鎖才行)

2. 線程狀態(tài)變成 WAITING

3. 線程進(jìn)入 lock 對(duì)象的等待隊(duì)列


什么時(shí)候這個(gè)線程被喚醒,從等待隊(duì)列中移出,并從 WAITING 狀態(tài)返回 RUNNABLE 狀態(tài)呢?

必須由另一個(gè)線程,調(diào)用同一個(gè)對(duì)象的 notify / notifyAll 方法。

new Thread(() - {
synchronized (lock) {
...
lock.notify();
...
}
}).start();

只不過(guò) notify 是只喚醒一個(gè)線程,而 notifyAll 是喚醒所有等待隊(duì)列中的線程。

但需要注意,被喚醒后的線程,從等待隊(duì)列移出,狀態(tài)變?yōu)?RUNNABLE,但仍然需要搶鎖,搶鎖成功了,才可以從 wait 方法返回,繼續(xù)執(zhí)行。

如果失敗了,就和上一部分的 BLOCKED 流程一樣了。


所以我們的整個(gè)流程圖,現(xiàn)在變成了這個(gè)樣子。


join

主線程這樣寫。

public static void main(String[] args) {
thread t = new Thread();
t.start();
t.join();
}

當(dāng)執(zhí)行到 t.join () 的時(shí)候,主線程會(huì)變成 WAITING 狀態(tài),直到線程 t 執(zhí)行完畢,主線程才會(huì)變回 RUNNABLE 狀態(tài),繼續(xù)往下執(zhí)行。

看起來(lái),就像是主線程執(zhí)行過(guò)程中,另一個(gè)線程插隊(duì)加入(join),而且要等到其結(jié)束后主線程才繼續(xù)。

因此我們的狀態(tài)圖,又多了兩項(xiàng)。

那 join 又是怎么神奇地實(shí)現(xiàn)這一切呢?也是像 wait 一樣放到等待隊(duì)列么?

打開 Thread.join () 的源碼,你會(huì)發(fā)現(xiàn)它非常簡(jiǎn)單。

// Thread.java
// 無(wú)參的 join 有用的信息就這些,省略了額外分支
public synchronized void join() {
while (isAlive()) {
wait();
}
}

也就是說(shuō),他的本質(zhì)仍然是執(zhí)行了 wait () 方法,而鎖對(duì)象就是 Thread t 對(duì)象本身。

那從 RUNNABLE 到 WAITING,就和執(zhí)行了 wait () 方法完全一樣了。

那從 WAITING 回到 RUNNABLE 是怎么實(shí)現(xiàn)的呢?

主線程調(diào)用了 wait ,需要另一個(gè)線程 notify 才行,難道需要這個(gè)子線程 t 在結(jié)束之前,調(diào)用一下 t.notifyAll () 么?

答案是否定的,那就只有一種可能,線程 t 結(jié)束后,由 jvm 自動(dòng)調(diào)用 t.notifyAll (),不用我們程序顯示寫出。

沒錯(cuò),就是這樣。

怎么證明這一點(diǎn)呢?道聽途說(shuō)可不行,老子今天非要扒開 jvm 的外套。

果然,找到了如下代碼。

hotspot/src/share/vm/runtime/thread.cpp
void JavaThread::exit(...) {
...
ensure_join(this);
...
}
static void ensure_join(JavaThread* thread) {
...
lock.notify_all(thread);
...
}

我們看到,虛擬機(jī)在一個(gè)線程的方法執(zhí)行完畢后,執(zhí)行了個(gè) ensure_join 方法,看名字就知道是專門為 join 而設(shè)計(jì)的。

而繼續(xù)跟進(jìn)會(huì)發(fā)現(xiàn)一段關(guān)鍵代碼,lock.notify_all,這便是一個(gè)線程結(jié)束后,會(huì)自動(dòng)調(diào)用自己的 notifyAll 方法的證明。

所以,其實(shí) join 就是 wait,線程結(jié)束就是 notifyAll。現(xiàn)在,是不是更清晰了。


park/unpark

有了上面 wait 和 notify 的機(jī)制,下面就好理解了。

一個(gè)線程調(diào)用如下方法。

LockSupport.park()

該線程狀態(tài)會(huì)從 RUNNABLE 變成 WAITING、

另一個(gè)線程調(diào)用

LockSupport.unpark (Thread 剛剛的線程)

剛剛的線程會(huì)從 WAITING 回到 RUNNABLE

但從線程狀態(tài)流轉(zhuǎn)來(lái)看,與 wait 和 notify 相同。

從實(shí)現(xiàn)機(jī)制上看,他們甚至更為簡(jiǎn)單。

1. park 和 unpark 無(wú)需事先獲取鎖,或者說(shuō)跟鎖壓根無(wú)關(guān)。

2. 沒有什么等待隊(duì)列一說(shuō),unpark 會(huì)精準(zhǔn)喚醒某一個(gè)確定的線程。

3. park 和 unpark 沒有順序要求,可以先調(diào)用 unpark

關(guān)于第三點(diǎn),就涉及到 park 的原理了,這里我只簡(jiǎn)單說(shuō)明。

線程有一個(gè)計(jì)數(shù)器,初始值為 0

調(diào)用 park 就是

如果這個(gè)值為 0,就將線程掛起,狀態(tài)改為 WAITING。如果這個(gè)值為 1,則將這個(gè)值改為 0,其余的什么都不做。

調(diào)用 unpark 就是

將這個(gè)值改為 1

然后我用三個(gè)例子,你就基本明白了。

// 例子1
LockSupport.unpark(Thread.currentThread()); // 1
LockSupport.park(); // 0
System.out.println("可以運(yùn)行到這");
// 例子2
LockSupport.unpark(Thread.currentThread()); // 1
LockSupport.unpark(Thread.currentThread()); // 1
LockSupport.park(); // 0
System.out.println("可以運(yùn)行到這");
// 例子3
LockSupport.unpark(Thread.currentThread()); // 1
LockSupport.unpark(Thread.currentThread()); // 1
LockSupport.park(); // 0
LockSupport.park(); // WAITING
System.out.println("不可以運(yùn)行到這");

park 的使用非常簡(jiǎn)單,同時(shí)也是 JDK 中鎖實(shí)現(xiàn)的底層。它的 JVM 及操作系統(tǒng)層面的原理很復(fù)雜,改天可以專門找一節(jié)來(lái)講解。

現(xiàn)在我們的狀態(tài)圖,又可以更新了。


TIMED_WAITING

這部分就再簡(jiǎn)單不過(guò)了,將上面導(dǎo)致線程變成 WAITING 狀態(tài)的那些方法,都增加一個(gè)超時(shí)參數(shù),就變成了將線程變成 TIMED_WAITING 狀態(tài)的方法了,我們直接更新流程圖。

這些方法的唯一區(qū)別就是,從 TIMED_WAITING 返回 RUNNABLE,不但可以通過(guò)之前的方式,還可以通過(guò)到了超時(shí)時(shí)間,返回 RUNNABLE 狀態(tài)。

就這樣。

還有,大家看。

wait 需要先獲取鎖,再釋放鎖,然后等待被 notify。

join 就是 wait 的封裝。

park 需要等待 unpark 來(lái)喚醒,或者提前被 unpark 發(fā)放了喚醒許可。

那有沒有一個(gè)方法,僅僅讓線程掛起,只能通過(guò)等待超時(shí)時(shí)間到了再被喚醒呢。

這個(gè)方法就是

Thread.sleep(long)

我們把它補(bǔ)充在圖里,這一部分就全了。

再把它加到全局圖中。


后記

Java 線程的狀態(tài),有六種

  1. NEW
  2. RUNNABLE
  3. BLOCKED
  4. WAITING
  5. TIMED_WAITING
  6. TERMINATED

而經(jīng)典的線程五態(tài)模型,有五種狀態(tài)

  1. 創(chuàng)建
  2. 就緒
  3. 執(zhí)行
  4. 阻塞
  5. 終止

不同實(shí)現(xiàn)者,可能有合并和拆分。

比如 Java 將五態(tài)模型中的就緒和執(zhí)行,都統(tǒng)一成 RUNNABLE,將阻塞(即不可能得到 CPU 運(yùn)行機(jī)會(huì)的狀態(tài))細(xì)分為了 BLOCKED、WAITING、TIMED_WAITING,這里我們不去評(píng)價(jià)好壞。

也就是說(shuō),BLOCKED、WAITING、TIMED_WAITING 這幾個(gè)狀態(tài),線程都不可能得到 CPU 的運(yùn)行權(quán),你叫它掛起、阻塞、睡眠、等待,都可以,很多文章,你也會(huì)看到這幾個(gè)詞沒那么較真地來(lái)回用。

再說(shuō)兩個(gè)你可能困惑的問(wèn)題。

調(diào)用 jdk 的 Lock 接口中的 lock,如果獲取不到鎖,線程將掛起,此時(shí)線程的狀態(tài)是什么呢?

有多少同學(xué)覺得應(yīng)該和 synchronized 獲取不到鎖的效果一樣,是變成 BLOCKED 狀態(tài)?

不過(guò)如果你仔細(xì)看我上面的文章,有一句話提到了,jdk 中鎖的實(shí)現(xiàn),是基于 AQS 的,而 AQS 的底層,是用 park 和 unpark 來(lái)掛起和喚醒線程,所以應(yīng)該是變?yōu)?WAITING 或 TIMED_WAITING 狀態(tài)。

調(diào)用阻塞 IO 方法,線程變成什么狀態(tài)?

比如 socket 編程時(shí),調(diào)用如 accept (),read () 這種阻塞方法時(shí),線程處于什么狀態(tài)呢?

答案是處于 RUNNABLE 狀態(tài),但實(shí)際上這個(gè)線程是得不到運(yùn)行權(quán)的,因?yàn)樵诓僮飨到y(tǒng)層面處于阻塞態(tài),需要等到 IO 就緒,才能變?yōu)榫途w態(tài)。

但是在 Java 層面,JVM 認(rèn)為等待 IO 與等待 CPU 執(zhí)行權(quán),都是一樣的,人家就是這么認(rèn)為的,這里我仍然不討論其好壞,你覺得這么認(rèn)為不爽,可以自己設(shè)計(jì)一門語(yǔ)言,那你想怎么認(rèn)為,別人也拿你沒辦法。

比如要我設(shè)計(jì)語(yǔ)言,我就認(rèn)為可被 CPU 調(diào)度執(zhí)行的線程,處于死亡態(tài)。這樣我的這門語(yǔ)言一定會(huì)有個(gè)經(jīng)典面試題,為什么閃客把可運(yùn)行的線程定義為死亡態(tài)呢?

OK,今天的文章就到這里。

本篇文章寫得有點(diǎn)投入,寫到這發(fā)現(xiàn)把開頭都小宇都給忘了。

責(zé)任編輯:龐桂玉 來(lái)源: IT之家
相關(guān)推薦

2022-03-23 08:51:21

線程池Java面試題

2019-02-25 17:42:43

TCP協(xié)議狀態(tài)轉(zhuǎn)換

2021-12-26 18:22:30

Java線程多線程

2021-12-28 09:10:55

Java線程狀態(tài)

2012-05-15 02:18:31

Java線程池

2024-11-28 11:07:50

線程JVM操作系統(tǒng)

2017-07-06 15:36:56

線程線程安全開發(fā)

2010-06-28 17:00:58

FTP傳輸模式

2015-08-13 10:48:39

Java 8轉(zhuǎn)換及改進(jìn)

2024-12-31 09:00:12

Java線程狀態(tài)

2013-12-09 09:56:30

NAT64IPv6stateful

2010-06-18 12:38:38

UML狀態(tài)機(jī)視圖

2023-11-29 16:29:09

線程java

2024-10-11 15:04:35

KafkaLeader選舉

2022-08-29 16:03:33

狀態(tài)流轉(zhuǎn)Java

2009-03-04 10:11:58

StringsjavaSun

2017-03-26 23:16:05

Java線程jstack

2017-06-09 15:17:48

Java線程jstack

2022-07-29 07:48:15

HTTP常用狀態(tài)碼

2010-05-27 14:42:40

Linux查看端口
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧美一区二区在线 | 麻豆毛片 | 亚洲国产成人在线视频 | 婷婷综合五月天 | 成人依人 | av免费网址| 99这里只有精品视频 | 亚洲精品一 | 久久久精品综合 | 欧美成人h版在线观看 | 欧美中文字幕一区二区三区亚洲 | 久久久久高清 | 久久综合九九 | 可以免费看的毛片 | av福利网 | 日韩成人精品在线观看 | 日韩av在线免费 | 国产视频久 | 精品亚洲一区二区 | 五月激情综合网 | 亚洲欧美精品在线观看 | 可以看黄的视频 | 免费一级毛片 | 中日字幕大片在线播放 | 午夜爽爽爽男女免费观看影院 | 欧美视频 亚洲视频 | 国产亚洲精品久久情网 | 日韩五月天| 波多野结衣精品在线 | 免费h视频| 黑人成人网| 狠狠亚洲 | 国产小视频在线观看 | 欧美在线综合 | 日韩一级免费大片 | 久久黄色网 | 一级片在线播放 | 国产视频二区在线观看 | 日本精品一区二区三区视频 | 欧美不卡一区二区 | 久久久精品一区二区三区四季av |