精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

用這四招優(yōu)雅地實現(xiàn) Spring Boot 異步線程間數(shù)據(jù)傳遞

開發(fā) 前端
TaskDecorator是什么?官方api的大致意思:這是一個執(zhí)行回調(diào)方法的裝飾器,主要應(yīng)用于傳遞上下文,或者提供任務(wù)的監(jiān)控/統(tǒng)計信息。

Spring Boot 自定義線程池實現(xiàn)異步開發(fā)相信看過陳某的文章都了解,但是在實際開發(fā)中需要在父子線程之間傳遞一些數(shù)據(jù),比如用戶信息,鏈路信息等等

比如用戶登錄信息使用ThreadLocal存放保證線程隔離,代碼如下:

/**
* @author 公眾號:碼猿技術(shù)專欄
* @description 用戶上下文信息
*/
public class OauthContext {
private static final ThreadLocal<LoginVal> loginValThreadLocal=new ThreadLocal<>();

public static LoginVal get(){
return loginValThreadLocal.get();
}
public static void set(LoginVal loginVal){
loginValThreadLocal.set(loginVal);
}
public static void clear(){
loginValThreadLocal.remove();
}
}

那么子線程想要獲取這個LoginVal如何做呢?

今天就來介紹幾種優(yōu)雅的方式實現(xiàn)Spring Boot 內(nèi)部的父子線程的數(shù)據(jù)傳遞。

圖片

1. 手動設(shè)置

每執(zhí)行一次異步線程都要分為兩步:

  • 獲取父線程的LoginVal
  • 將LoginVal設(shè)置到子線程,達到復(fù)用

代碼如下:

public void handlerAsync() {
//1. 獲取父線程的loginVal
LoginVal loginVal = OauthContext.get();
log.info("父線程的值:{}",OauthContext.get());
CompletableFuture.runAsync(()->{
//2. 設(shè)置子線程的值,復(fù)用
OauthContext.set(loginVal);
log.info("子線程的值:{}",OauthContext.get());
});
}

雖然能夠?qū)崿F(xiàn)目的,但是每次開異步線程都需要手動設(shè)置,重復(fù)代碼太多,看了頭疼,你認為優(yōu)雅嗎?

2. 線程池設(shè)置TaskDecorator

TaskDecorator是什么?官方api的大致意思:這是一個執(zhí)行回調(diào)方法的裝飾器,主要應(yīng)用于傳遞上下文,或者提供任務(wù)的監(jiān)控/統(tǒng)計信息。

知道有這么一個東西,如何去使用?

TaskDecorator是一個接口,首先需要去實現(xiàn)它,代碼如下:

/**
* @author 公眾號:碼猿技術(shù)專欄
* @description 上下文裝飾器
*/
public class ContextTaskDecorator implements TaskDecorator {
@Override
public Runnable decorate(Runnable runnable) {
//獲取父線程的loginVal
LoginVal loginVal = OauthContext.get();
return () -> {
try {
// 將主線程的請求信息,設(shè)置到子線程中
OauthContext.set(loginVal);
// 執(zhí)行子線程,這一步不要忘了
runnable.run();
} finally {
// 線程結(jié)束,清空這些信息,否則可能造成內(nèi)存泄漏
OauthContext.clear();
}
};
}
}

這里我只是設(shè)置了LoginVal,實際開發(fā)中其他的共享數(shù)據(jù),比如SecurityContext,RequestAttributes....

TaskDecorator需要結(jié)合線程池使用,實際開發(fā)中異步線程建議使用線程池,只需要在對應(yīng)的線程池配置一下,代碼如下:

@Bean("taskExecutor")
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor();
poolTaskExecutor.setCorePoolSize(xx);
poolTaskExecutor.setMaxPoolSize(xx);
// 設(shè)置線程活躍時間(秒)
poolTaskExecutor.setKeepAliveSeconds(xx);
// 設(shè)置隊列容量
poolTaskExecutor.setQueueCapacity(xx);
//設(shè)置TaskDecorator,用于解決父子線程間的數(shù)據(jù)復(fù)用
poolTaskExecutor.setTaskDecorator(new ContextTaskDecorator());
poolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任務(wù)結(jié)束后再關(guān)閉線程池
poolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
return poolTaskExecutor;
}

此時業(yè)務(wù)代碼就不需要去設(shè)置子線程的值,直接使用即可,代碼如下:

public void handlerAsync() {
log.info("父線程的用戶信息:{}", OauthContext.get());
//執(zhí)行異步任務(wù),需要指定的線程池
CompletableFuture.runAsync(()-> log.info("子線程的用戶信息:{}", OauthContext.get()),taskExecutor);
}

來看一下結(jié)果,如下圖:

圖片

這里使用的是CompletableFuture執(zhí)行異步任務(wù),使用@Async這個注解同樣是可行的。

注意:無論使用何種方式,都需要指定線程池

3. InheritableThreadLocal

這種方案不建議使用,InheritableThreadLocal雖然能夠?qū)崿F(xiàn)父子線程間的復(fù)用,但是在線程池中使用會存在復(fù)用的問題。

這種方案使用也是非常簡單,直接用InheritableThreadLocal替換ThreadLocal即可,代碼如下:

/**
* @author 公眾號:碼猿技術(shù)專欄
* @description 用戶上下文信息
*/
public class OauthContext {
private static final InheritableThreadLocal<LoginVal> loginValThreadLocal=new InheritableThreadLocal<>();

public static LoginVal get(){
return loginValThreadLocal.get();
}
public static void set(LoginVal loginVal){
loginValThreadLocal.set(loginVal);
}
public static void clear(){
loginValThreadLocal.remove();
}
}

4. TransmittableThreadLocal

TransmittableThreadLocal是阿里開源的工具,彌補了InheritableThreadLocal的缺陷,在使用線程池等會池化復(fù)用線程的執(zhí)行組件情況下,提供??ThreadLocal??值的傳遞功能,解決異步執(zhí)行時上下文傳遞的問題。

使用起來也是非常簡單,添加依賴如下:

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>2.14.2</version>
</dependency>

OauthContext改造代碼如下:

/**
* @author 公眾號:碼猿技術(shù)專欄
* @description 用戶上下文信息
*/
public class OauthContext {
private static final TransmittableThreadLocal<LoginVal> loginValThreadLocal=new TransmittableThreadLocal<>();

public static LoginVal get(){
return loginValThreadLocal.get();
}
public static void set(LoginVal loginVal){
loginValThreadLocal.set(loginVal);
}
public static void clear(){
loginValThreadLocal.remove();
}
}

TransmittableThreadLocal原理

從定義來看,TransimittableThreadLocal繼承于InheritableThreadLocal,并實現(xiàn)TtlCopier接口,它里面只有一個copy方法。所以主要是對InheritableThreadLocal的擴展。

public class TransmittableThreadLocal<T> extends InheritableThreadLocal<T> implements TtlCopier<T>

在TransimittableThreadLocal中添加holder屬性。這個屬性的作用就是被標記為具備線程傳遞資格的對象都會被添加到這個對象中。

要標記一個類,比較容易想到的方式,就是給這個類新增一個Type字段,還有一個方法就是將具備這種類型的的對象都添加到一個靜態(tài)全局集合中。之后使用時,這個集合里的所有值都具備這個標記。

// 1. holder本身是一個InheritableThreadLocal對象
// 2. 這個holder對象的value是WeakHashMap<TransmittableThreadLocal<Object>, ?>
// 2.1 WeekHashMap的value總是null,且不可能被使用。
// 2.2 WeekHasshMap支持value=null
private static InheritableThreadLocal<WeakHashMap<TransmittableThreadLocal<Object>, ?>> holder = new InheritableThreadLocal<WeakHashMap<TransmittableThreadLocal<Object>, ?>>() {
@Override
protected WeakHashMap<TransmittableThreadLocal<Object>, ?> initialValue() {
return new WeakHashMap<TransmittableThreadLocal<Object>, Object>();
}

/**
* 重寫了childValue方法,實現(xiàn)上直接將父線程的屬性作為子線程的本地變量對象。
*/
@Override
protected WeakHashMap<TransmittableThreadLocal<Object>, ?> childValue(WeakHashMap<TransmittableThreadLocal<Object>, ?> parentValue) {
return new WeakHashMap<TransmittableThreadLocal<Object>, Object>(parentValue);
}
};

應(yīng)用代碼是通過TtlExecutors工具類對線程池對象進行包裝。工具類只是簡單的判斷,輸入的線程池是否已經(jīng)被包裝過、非空校驗等,然后返回包裝類ExecutorServiceTtlWrapper。根據(jù)不同的線程池類型,有不同和的包裝類。

@Nullable
public static ExecutorService getTtlExecutorService(@Nullable ExecutorService executorService) {
if (TtlAgent.isTtlAgentLoaded() || executorService == null || executorService instanceof TtlEnhanced) {
return executorService;
}
return new ExecutorServiceTtlWrapper(executorService);
}

進入包裝類ExecutorServiceTtlWrapper。可以注意到不論是通過ExecutorServiceTtlWrapper#submit方法或者是ExecutorTtlWrapper#execute方法,都會將線程對象包裝成TtlCallable或者TtlRunnable,用于在真正執(zhí)行run方法前做一些業(yè)務(wù)邏輯。

/**
* 在ExecutorServiceTtlWrapper實現(xiàn)submit方法
*/
@NonNull
@Override
public <T> Future<T> submit(@NonNull Callable<T> task) {
return executorService.submit(TtlCallable.get(task));
}

/**
* 在ExecutorTtlWrapper實現(xiàn)execute方法
*/
@Override
public void execute(@NonNull Runnable command) {
executor.execute(TtlRunnable.get(command));
}

所以,重點的核心邏輯應(yīng)該是在TtlCallable#call()或者TtlRunnable#run()中。以下以TtlCallable為例,TtlRunnable同理類似。在分析call()方法之前,先看一個類Transmitter。

public static class Transmitter {
/**
* 捕獲當前線程中的是所有TransimittableThreadLocal和注冊ThreadLocal的值。
*/
@NonNull
public static Object capture() {
return new Snapshot(captureTtlValues(), captureThreadLocalValues());
}

/**
* 捕獲TransimittableThreadLocal的值,將holder中的所有值都添加到HashMap后返回。
*/
private static HashMap<TransmittableThreadLocal<Object>, Object> captureTtlValues() {
HashMap<TransmittableThreadLocal<Object>, Object> ttl2Value =
new HashMap<TransmittableThreadLocal<Object>, Object>();
for (TransmittableThreadLocal<Object> threadLocal : holder.get().keySet()) {
ttl2Value.put(threadLocal, threadLocal.copyValue());
}
return ttl2Value;
}

/**
* 捕獲注冊的ThreadLocal的值,也就是原本線程中的ThreadLocal,可以注冊到TTL中,在
* 進行線程池本地變量傳遞時也會被傳遞。
*/
private static HashMap<ThreadLocal<Object>, Object> captureThreadLocalValues() {
final HashMap<ThreadLocal<Object>, Object> threadLocal2Value =
new HashMap<ThreadLocal<Object>, Object>();
for(Map.Entry<ThreadLocal<Object>,TtlCopier<Object>>entry:threadLocalHolder.entrySet()){
final ThreadLocal<Object> threadLocal = entry.getKey();
final TtlCopier<Object> copier = entry.getValue();
threadLocal2Value.put(threadLocal, copier.copy(threadLocal.get()));
}
return threadLocal2Value;
}

/**
* 將捕獲到的本地變量進行替換子線程的本地變量,并且返回子線程現(xiàn)有的本地變量副本backup。
* 用于在執(zhí)行run/call方法之后,將本地變量副本恢復(fù)。
*/
@NonNull
public static Object replay(@NonNull Object captured) {
final Snapshot capturedSnapshot = (Snapshot) captured;
return new Snapshot(replayTtlValues(capturedSnapshot.ttl2Value),
replayThreadLocalValues(capturedSnapshot.threadLocal2Value));
}

/**
* 替換TransmittableThreadLocal
*/
@NonNull
private static HashMap<TransmittableThreadLocal<Object>, Object> replayTtlValues(@NonNull HashMap<TransmittableThreadLocal<Object>, Object> captured) {
// 創(chuàng)建副本backup
HashMap<TransmittableThreadLocal<Object>, Object> backup =
new HashMap<TransmittableThreadLocal<Object>, Object>();

for (final Iterator<TransmittableThreadLocal<Object>> iterator = holder.get().keySet().iterator(); iterator.hasNext(); ) {
TransmittableThreadLocal<Object> threadLocal = iterator.next();
// 對當前線程的本地變量進行副本拷貝
backup.put(threadLocal, threadLocal.get());

// 若出現(xiàn)調(diào)用線程中不存在某個線程變量,而線程池中線程有,則刪除線程池中對應(yīng)的本地變量
if (!captured.containsKey(threadLocal)) {
iterator.remove();
threadLocal.superRemove();
}
}
// 將捕獲的TTL值打入線程池獲取到的線程TTL中。
setTtlValuesTo(captured);
// 是一個擴展點,調(diào)用TTL的beforeExecute方法。默認實現(xiàn)為空
doExecuteCallback(true);
return backup;
}

private static HashMap<ThreadLocal<Object>, Object> replayThreadLocalValues(@NonNull HashMap<ThreadLocal<Object>, Object> captured) {
final HashMap<ThreadLocal<Object>, Object> backup =
new HashMap<ThreadLocal<Object>, Object>();
for (Map.Entry<ThreadLocal<Object>, Object> entry : captured.entrySet()) {
final ThreadLocal<Object> threadLocal = entry.getKey();
backup.put(threadLocal, threadLocal.get());
final Object value = entry.getValue();
if (value == threadLocalClearMark) threadLocal.remove();
else threadLocal.set(value);
}
return backup;
}

/**
* 清除單線線程的所有TTL和TL,并返回清除之氣的backup
*/
@NonNull
public static Object clear() {
final HashMap<TransmittableThreadLocal<Object>, Object> ttl2Value =
new HashMap<TransmittableThreadLocal<Object>, Object>();

final HashMap<ThreadLocal<Object>, Object> threadLocal2Value =
new HashMap<ThreadLocal<Object>, Object>();
for(Map.Entry<ThreadLocal<Object>,TtlCopier<Object>>entry:threadLocalHolder.entrySet()){
final ThreadLocal<Object> threadLocal = entry.getKey();
threadLocal2Value.put(threadLocal, threadLocalClearMark);
}
return replay(new Snapshot(ttl2Value, threadLocal2Value));
}

/**
* 還原
*/
public static void restore(@NonNull Object backup) {
final Snapshot backupSnapshot = (Snapshot) backup;
restoreTtlValues(backupSnapshot.ttl2Value);
restoreThreadLocalValues(backupSnapshot.threadLocal2Value);
}

private static void restoreTtlValues(@NonNull HashMap<TransmittableThreadLocal<Object>, Object> backup) {
// 擴展點,調(diào)用TTL的afterExecute
doExecuteCallback(false);

for (final Iterator<TransmittableThreadLocal<Object>> iterator = holder.get().keySet().iterator(); iterator.hasNext(); ) {
TransmittableThreadLocal<Object> threadLocal = iterator.next();

if (!backup.containsKey(threadLocal)) {
iterator.remove();
threadLocal.superRemove();
}
}

// 將本地變量恢復(fù)成備份版本
setTtlValuesTo(backup);
}

private static void setTtlValuesTo(@NonNull HashMap<TransmittableThreadLocal<Object>, Object> ttlValues) {
for (Map.Entry<TransmittableThreadLocal<Object>, Object> entry : ttlValues.entrySet()) {
TransmittableThreadLocal<Object> threadLocal = entry.getKey();
threadLocal.set(entry.getValue());
}
}

private static void restoreThreadLocalValues(@NonNull HashMap<ThreadLocal<Object>, Object> backup) {
for (Map.Entry<ThreadLocal<Object>, Object> entry : backup.entrySet()) {
final ThreadLocal<Object> threadLocal = entry.getKey();
threadLocal.set(entry.getValue());
}
}

/**
* 快照類,保存TTL和TL
*/
private static class Snapshot {
final HashMap<TransmittableThreadLocal<Object>, Object> ttl2Value;
final HashMap<ThreadLocal<Object>, Object> threadLocal2Value;

private Snapshot(HashMap<TransmittableThreadLocal<Object>, Object> ttl2Value,
HashMap<ThreadLocal<Object>, Object> threadLocal2Value) {
this.ttl2Value = ttl2Value;
this.threadLocal2Value = threadLocal2Value;
}
}

進入??TtlCallable#call()??方法。

@Override
public V call() throws Exception {
Object captured = capturedRef.get();
if (captured == null || releaseTtlValueReferenceAfterCall &&
!capturedRef.compareAndSet(captured, null)) {
throw new IllegalStateException("TTL value reference is released after call!");
}
// 調(diào)用replay方法將捕獲到的當前線程的本地變量,傳遞給線程池線程的本地變量,
// 并且獲取到線程池線程覆蓋之前的本地變量副本。
Object backup = replay(captured);
try {
// 線程方法調(diào)用
return callable.call();
} finally {
// 使用副本進行恢復(fù)。
restore(backup);
}
}

到這基本上線程池方式傳遞本地變量的核心代碼已經(jīng)大概看完了。總的來說在創(chuàng)建TtlCallable對象是,調(diào)用capture()方法捕獲調(diào)用方的本地線程變量,在call()執(zhí)行時,將捕獲到的線程變量,替換到線程池所對應(yīng)獲取到的線程的本地變量中,并且在執(zhí)行完成之后,將其本地變量恢復(fù)到調(diào)用之前。

總結(jié)

上述列舉了4種方案,陳某這里推薦方案2和方案4,其中兩種方案的缺點非常明顯,實際開發(fā)中也是采用的方案2或者方案4。

責(zé)任編輯:武曉燕 來源: 碼猿技術(shù)專欄
相關(guān)推薦

2024-11-25 13:49:00

2011-07-13 09:31:48

ASP.NET數(shù)據(jù)傳遞

2024-11-13 16:37:00

Java線程池

2009-12-16 09:16:53

ASP.NET頁面間數(shù)

2020-12-08 08:08:51

Java接口數(shù)據(jù)

2025-03-11 00:55:00

Spring停機安全

2025-05-29 01:33:00

微服務(wù)架構(gòu)系統(tǒng)

2021-02-09 09:51:58

異步傳遞數(shù)據(jù)

2017-12-14 14:17:08

Windows使用技巧手冊

2024-04-24 12:34:08

Spring事務(wù)編程

2017-05-22 11:09:53

KotlinAndroid

2022-09-29 09:19:04

線程池并發(fā)線程

2018-06-21 14:46:03

Spring Boot異步調(diào)用

2023-05-12 14:14:00

Java線程中斷

2024-08-06 09:43:54

Java 8工具編程

2023-06-06 08:51:06

2021-05-12 22:07:43

并發(fā)編排任務(wù)

2025-03-28 08:34:34

2020-03-27 15:10:23

SpringJava框架

2025-11-10 03:15:00

線程池asyncToolSpring
點贊
收藏

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

国产成人免费高清视频| 国产精品专区一| 亚洲熟女一区二区| 性欧美18xxxhd| 久久精品一区蜜桃臀影院| 国产精品美女av| 亚洲熟女www一区二区三区| 都市激情亚洲欧美| 色狠狠av一区二区三区| 色中文字幕在线观看| 风流少妇一区二区三区91| 蘑菇福利视频一区播放| 中文字幕欧美国内| 中文字幕人妻一区| 九色成人搞黄网站| 亚洲一区二区av电影| 欧美不卡三区| 国产精品毛片久久久久久久av| 激情五月***国产精品| 亚洲九九九在线观看| 777一区二区| 国产直播在线| 成人免费视频在线观看| 精品欧美国产| 国产免费黄色录像| 久久一区二区三区超碰国产精品| 久久夜色精品国产| 中文字幕一区二区三区人妻电影| 精品一区二区三区视频在线播放| 欧美午夜性色大片在线观看| 青草全福视在线| 国产综合视频一区二区三区免费| 国产成人啪免费观看软件| 国产不卡av在线免费观看| 久久久久亚洲av无码专区| 欧美一区二区三| 亚洲国产中文字幕久久网| 欧美视频国产视频| 日本欧美韩国| 狠狠色狠狠色综合日日小说| 国产成人一区二区三区别| 一区二区三区视频网站 | 中文字幕一区二区三| 久久riav| 欧美一级特黄aaaaaa| 精一区二区三区| 国产成人精品在线视频| 欧美亚洲天堂网| 午夜久久影院| 久久精品国产亚洲| 精品人体无码一区二区三区| 偷拍亚洲精品| 亚洲精品福利在线观看| 国产a级片视频| 日韩精品一区二区三区中文在线 | 久草福利视频在线| 中文字幕乱码在线播放| 天天爽夜夜爽夜夜爽精品视频| 日韩视频 中文字幕| 黄色av电影在线观看| 中文av字幕一区| 先锋在线资源一区二区三区| 日本在线视频1区| 91老师片黄在线观看| 黄色91av| 深夜视频在线免费| 97国产精品videossex| 国产在线一区二区三区欧美 | 91大神在线观看线路一区| 色老综合老女人久久久| jizz欧美激情18| 免费在线成人激情电影| 欧美三区免费完整视频在线观看| 一本色道无码道dvd在线观看| 怡红院成人在线| 欧美在线小视频| 伊人国产在线视频| 高清一区二区| 欧美成人官网二区| 一起草在线视频| 免费精品国产的网站免费观看| 亚洲人成网站777色婷婷| 色综合99久久久无码国产精品| 精品美女视频| 久久精品青青大伊人av| 日本中文字幕免费在线观看| 亚洲大胆视频| 欧美最猛性xxxx| 中文字幕欧美人妻精品| 国产乱码精品一区二区三区av| 成人在线免费观看一区| 日本韩国一区| 国产精品久久久久久久久果冻传媒| 黄频视频在线观看| 999av小视频在线| 欧美香蕉大胸在线视频观看| 日韩肉感妇bbwbbwbbw| 麻豆精品在线| 亚洲欧美激情一区| 少妇高潮在线观看| 日韩视频久久| 国产日韩精品在线播放| 亚洲国产精品二区| 国产欧美一区在线| 成人免费看片'免费看| 成人欧美一区二区三区的电影| 欧美精品成人一区二区三区四区| 性活交片大全免费看| 国内精品久久久久久99蜜桃| 久久午夜a级毛片| 欧美精品一二三四区| 国产在线国偷精品产拍免费yy| 国产麻豆一区二区三区在线观看| www.91在线| 午夜精品久久久久久| 国产精品一区二区小说| 日韩av不卡一区| 久久色在线播放| 四虎成人在线观看| 丰满岳乱妇一区二区三区| 无码免费一区二区三区免费播放| xxx.xxx欧美| 4438x亚洲最大成人网| 成人手机在线免费视频| 亚洲欧美一区在线| 国产精品无码专区在线观看| 青青青手机在线视频观看| 亚洲精品视频免费看| 免费观看成人网| 国产96在线亚洲| 精品久久久av| 这里只有精品999| 91蝌蚪国产九色| 97干在线视频| 午夜日韩影院| 久久精品国产精品亚洲| 中文字幕精品在线观看| 26uuu精品一区二区三区四区在线 26uuu精品一区二区在线观看 | 欧美日韩在线中文| 国产成人精品亚洲线观看| 久久久精品亚洲| 又污又黄的网站| 久久精品亚洲乱码伦伦中文 | 成熟的女同志hd| 国产综合色精品一区二区三区| 午夜精品一区二区三区四区 | 成人在线精品视频| 午夜国产福利在线| 在线区一区二视频| 欧洲美熟女乱又伦| 三级久久三级久久久| 乱一区二区三区在线播放| gogo高清在线播放免费| 精品电影一区二区| 男人天堂中文字幕| 成人毛片视频在线观看| 农民人伦一区二区三区| 高清日韩中文字幕| 91国产美女视频| 五月天丁香视频| 精品久久久久久中文字幕大豆网| 少妇激情一区二区三区视频| 日韩午夜黄色| 久久精品ww人人做人人爽| 色是在线视频| 亚洲欧美在线免费| 精品国产www| 1区2区3区精品视频| 韩国av中国字幕| 亚洲国产网站| 欧美一区1区三区3区公司| av在线日韩| www国产精品com| 国产成人精品免费看视频| 亚洲一区二区在线观看视频| 亚洲国产精品成人综合久久久| 免费亚洲视频| 亚洲综合五月天| 麻豆精品久久| 欧美在线激情网| 日本在线看片免费人成视1000| 欧美一区二区三区视频免费| 久久久久久久久久综合 | 成年人看的免费视频| 极品尤物av久久免费看| 久久久久久久9| 亚洲性视频大全| 国产伊人精品在线| 国产高清在线a视频大全| 亚洲欧美日韩中文在线| 7777久久亚洲中文字幕| 亚洲高清免费在线| 一级特黄曰皮片视频| 国产精品一区在线观看乱码| 六月丁香激情网| 999久久久亚洲| 国产伦精品一区二区三区高清版| 综合在线影院| 欧美乱妇高清无乱码| 可以在线观看的av网站| 91精品中文字幕一区二区三区| www.天天色| 国产精品第五页| 国产精品无码在线| 精品一区中文字幕| 青青草视频在线免费播放| 色综合天天爱| 九色综合婷婷综合| 国产精品1区在线| 国产成人短视频| 色屁屁www国产馆在线观看| 亚洲色图欧美制服丝袜另类第一页| 国产精品伦一区二区三区| 色综合久久天天| 久久免费在线观看视频| 国产精品毛片a∨一区二区三区| 日韩综合第一页| 国产一二三精品| 精品久久久噜噜噜噜久久图片| 欧美激情视频一区二区三区免费| 欧美日韩精品久久久免费观看| 免费一级欧美在线大片| 国产精品第2页| 国产污视频在线播放| 久久精品影视伊人网| 欧美婷婷久久五月精品三区| 日韩欧美精品三级| 一级黄色大片免费观看| 日本精品一区二区三区高清 | 中文字幕一区二区三区人妻电影| 国产福利一区二区三区| 国产成年人视频网站| 久久人人精品| 18禁免费无码无遮挡不卡网站| 国产综合自拍| 男女激烈动态图| 99久久精品国产亚洲精品| 日韩精品成人一区二区在线观看| 青草久久视频| 国产在线精品一区二区三区| 盗摄系列偷拍视频精品tp| 51国偷自产一区二区三区| 色综合视频一区二区三区日韩| 国产suv精品一区二区| 亚洲黄色免费看| 8x拔播拔播x8国产精品| 国产一二在线播放| 992tv在线成人免费观看| av资源网在线播放| 97精品免费视频| 九色porny丨国产首页在线| 性欧美亚洲xxxx乳在线观看| 国产乱码在线| 91国产一区在线| 第一中文字幕在线| 亚州精品天堂中文字幕| 国产精品论坛| 青草热久免费精品视频| 欧美成人性网| 国产精品96久久久久久又黄又硬| 日本成人伦理电影| 国产精品香蕉在线观看| 欧美日韩伦理一区二区| 成人午夜黄色影院| 欧美午夜在线播放| 成人精品一二区| 国产精品久久久网站| 久久精品成人一区二区三区蜜臀| 国产传媒欧美日韩成人精品大片| 日本在线免费观看一区| 久久人体视频| 99中文字幕在线观看| 亚洲每日在线| 黄色一级大片在线观看| 久久精品国产一区二区三| 无套内谢丰满少妇中文字幕| 成人小视频免费在线观看| 亚洲国产综合视频| 国产欧美日韩视频一区二区| 天天鲁一鲁摸一摸爽一爽| 亚洲宅男天堂在线观看无病毒| 久久久国产高清| 色www精品视频在线观看| 11024精品一区二区三区日韩| 欧美不卡在线视频| 青青草观看免费视频在线 | 国产精品69xx| 国产精品国产自产拍高清av水多| 高清不卡一区| 久久精品欧美| 亚洲国产一区二区三区在线播放| 欧美午夜性视频| 奇米色一区二区| 91成人在线观看喷潮蘑菇| 国产午夜精品在线观看| 免费视频网站www| 在线一区二区三区| 午夜精品久久久久久久91蜜桃| 日韩精品在线观看网站| 国产在线更新| 人妖精品videosex性欧美| 国产精品毛片无码| 蜜桃av噜噜一区二区三区| 婷婷精品进入| 国产欧美在线一区| 国产精品亚洲第一区在线暖暖韩国| 青青草视频成人| 亚洲欧美日韩国产另类专区| 国产剧情在线视频| 精品免费一区二区三区| 97电影在线看视频| 77777亚洲午夜久久多人| 色婷婷成人网| 日产国产精品精品a∨| 国产一区日韩一区| www亚洲成人| 91免费在线看| 久久久香蕉视频| 欧美精品第一页| av在线电影院| 欧美尤物巨大精品爽| 7m精品国产导航在线| 中文字幕中文字幕在线中心一区 | 欧美色婷婷久久99精品红桃| a级黄色小视频| 国产一本一道久久香蕉| 91视频免费看片| 91精品91久久久中77777| 开心激情综合网| 欧美成人久久久| 欧美啪啪网站| 亚洲一区3d动漫同人无遮挡| 日日夜夜精品视频天天综合网| 男男做爰猛烈叫床爽爽小说| 亚洲黄网站在线观看| 91精品国自产| 日日骚久久av| 欧美日韩破处视频| 亚洲欧洲精品一区二区| 日韩成人dvd| 黄免费在线观看| 色婷婷激情综合| 麻豆影视在线| 国产成人精品日本亚洲| 香蕉久久夜色精品国产更新时间| 成人毛片100部免费看| 国产伦精品一区二区三区免费 | jvid一区二区三区| 亚洲高清不卡一区| 玖玖国产精品视频| 最近中文字幕无免费| 亚洲国产成人av好男人在线观看| 亚洲av无码乱码国产精品| 色婷婷综合久久久久| 国产精欧美一区二区三区蓝颜男同| 久久国产精品一区二区三区四区| 影音先锋一区| www.超碰97| 欧美视频一二三| 大乳在线免费观看| 国产成人精品综合久久久| 欧美自拍一区| 久久婷婷五月综合色国产香蕉| 99久久er热在这里只有精品15| 亚洲午夜18毛片在线看| 亚洲精品一区二区在线| 欧美一区国产| 麻豆传媒一区| 久久这里有精品15一区二区三区| 国产男男chinese网站| 一本色道亚洲精品aⅴ| 欧美成人高清在线| 国产一区在线播放| 激情亚洲网站| 最新在线黄色网址| 欧美性生交xxxxxdddd| 成年人在线观看| 国产精品va在线播放我和闺蜜| 成人免费电影网址| 中文字幕精品一区二区三区在线| 怡红院av一区二区三区| 丰满岳乱妇国产精品一区| 热99精品里视频精品| gogogo高清在线观看一区二区| 中文字幕 日韩 欧美| 亚洲色图另类专区| 一级aaaa毛片| 久久久爽爽爽美女图片| 日本在线中文字幕一区| 亚洲综合av在线播放| 亚洲欧洲综合另类| 日中文字幕在线| 国产精品日本精品| 黑丝一区二区三区| 久久久久久久人妻无码中文字幕爆| 偷拍与自拍一区| 懂色av中文在线| 91九色在线观看| 亚洲欧美网站| 久久综合综合久久|