日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 检视_Java高并发系列——检视阅读(五)

發布時間:2025/3/12 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 检视_Java高并发系列——检视阅读(五) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

JUC中工具類CompletableFuture

CompletableFuture是java8中新增的一個類,算是對Future的一種增強,用起來很方便,也是會經常用到的一個工具類,熟悉一下。

CompletionStage接口

CompletionStage代表異步計算過程中的某一個階段,一個階段完成以后可能會觸發另外一個階段

一個階段的計算執行可以是一個Function,Consumer或者Runnable。比如:stage.thenApply(x -> square(x)).thenAccept(x -> System.out.print(x)).thenRun(() -> System.out.println())

一個階段的執行可能是被單個階段的完成觸發,也可能是由多個階段一起觸發

CompletableFuture類

在Java8中,CompletableFuture提供了非常強大的Future的擴展功能,可以幫助我們簡化異步編程的復雜性,并且提供了函數式編程的能力,可以通過回調的方式處理計算結果,也提供了轉換和組合 CompletableFuture 的方法。

它可能代表一個明確完成的Future,也有可能代表一個完成階段( CompletionStage ),它支持在計算完成以后觸發一些函數或執行某些動作。

它實現了Future和CompletionStage接口

常見的方法,熟悉一下:

runAsync 和 supplyAsync方法

CompletableFuture 提供了四個靜態方法來創建一個異步操作。

public static CompletableFuture runAsync(Runnable runnable)

public static CompletableFuture runAsync(Runnable runnable, Executor executor)

public static CompletableFuture supplyAsync(Supplier supplier)

public static CompletableFuture supplyAsync(Supplier supplier, Executor executor)

沒有指定Executor的方法會使用ForkJoinPool.commonPool() 作為它的線程池執行異步代碼。如果指定線程池,則使用指定的線程池運行。以下所有的方法都類同。

runAsync方法不支持返回值。

supplyAsync可以支持返回值。

示例:

public class CompletableFutureTest1 {

public static void main(String[] args) throws Exception {

CompletableFutureTest1.runAsync();

CompletableFutureTest1.supplyAsync();

}

//runAsync方法不支持返回值 Runnable

public static void runAsync() throws Exception {

CompletableFuture future = CompletableFuture.runAsync(() -> {

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

}

System.out.println("run end ...");

});

future.get();

}

//supplyAsync可以支持返回值 Supplier

public static void supplyAsync() throws Exception {

CompletableFuture future = CompletableFuture.supplyAsync(() -> {

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

}

System.out.println("run end ...");

return System.currentTimeMillis();

});

//如果沒有future.get()阻塞等待結果的話,因為CompletableFuture.supplyAsync()方法默認是守護線程形式執行任務,在主線程結束后會跟著退出,

// 如果傳入的是線程池去執行,這不是守護線程,不會導致退出

long time = future.get();

System.out.println("time = "+time);

}

}

輸出:

run end ...

run end ...

time = 1599556248764

計算結果完成時的回調方法

當CompletableFuture的計算結果完成,或者拋出異常的時候,可以執行特定的Action。主要是下面的方法:

public CompletableFuture whenComplete(BiConsumer super T,? super Throwable> action)

public CompletableFuture whenCompleteAsync(BiConsumer super T,? super Throwable> action)

public CompletableFuture whenCompleteAsync(BiConsumer super T,? super Throwable> action, Executor executor)

public CompletableFuture exceptionally(Function fn)

可以看到Action的類型是BiConsumer它可以處理正常的計算結果,或者異常情況。

whenComplete 和 whenCompleteAsync 的區別:

whenComplete:當前任務的線程繼續執行 whenComplete 的任務。

whenCompleteAsync:把 whenCompleteAsync 這個任務繼續提交給線程池來進行執行。

示例:

public class CompletableFutureTest1 {

public static void main(String[] args) throws Exception {

CompletableFutureTest1.whenComplete();

CompletableFutureTest1.whenCompleteBySupply();

}

public static void whenComplete() throws Exception {

CompletableFuture future = CompletableFuture.runAsync(() -> {

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

}

if (new Random().nextInt() % 2 >= 0) {

int i = 12 / 0;

//run end ...

//執行完成!

//int i = 12 / 0;

}

System.out.println("run end ...");

});

//對執行成功或者執行異常做處理的回調方法

future.whenComplete((avoid, throwable) -> {

//先判斷是否拋異常分開處理

if (throwable != null) {

System.out.println("執行失敗!" + throwable.getMessage());

} else {

System.out.println("執行完成!");

}

});

//對執行異常做處理的回調方法

future.exceptionally(throwable -> {

System.out.println("執行失敗!" + throwable.getMessage());

return null;

}

);

TimeUnit.SECONDS.sleep(2);

}

public static void whenCompleteBySupply() throws Exception {

CompletableFuture future = CompletableFuture.supplyAsync(() -> {

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

}

if (new Random().nextInt() % 2 >= 0) {

//int i = 12 / 0;

//run end ...

//執行完成!

//int i = 12 / 0;

}

System.out.println("run end ...");

return "success";

});

//whenComplete在thenAccept之前執行

future.thenAccept(result -> {

System.out.println(result);

});

//對執行成功或者執行異常做處理的回調方法

future.whenComplete((avoid, throwable) -> {

//先判斷是否拋異常分開處理

if (throwable != null) {

System.out.println("執行失敗!" + throwable.getMessage());

} else {

System.out.println("執行完成!");

}

});

//對執行異常做處理的回調方法

future.exceptionally(throwable -> {

System.out.println("執行失敗!" + throwable.getMessage());

return null;

}

);

TimeUnit.SECONDS.sleep(2);

}

}

輸出:

執行失敗!java.lang.ArithmeticException: / by zero

執行失敗!java.lang.ArithmeticException: / by zero

run end ...

執行完成!

success

thenApply 方法

當一個線程依賴另一個線程時,可以使用 thenApply、thenApplyAsync 方法來把這兩個線程串行化。

public CompletableFuture thenApply(Function super T,? extends U> fn)

public CompletableFuture thenApplyAsync(Function super T,? extends U> fn)

public CompletableFuture thenApplyAsync(Function super T,? extends U> fn, Executor executor)

Function super T,? extends U>

T:上一個任務返回結果的類型

U:當前任務的返回值類型

示例:

public class CompletableFutureTest2 {

public static void main(String[] args) throws Exception {

CompletableFutureTest2.thenApply();

}

//多個CompletableFuture可以串行執行

//當一個線程依賴另一個線程時,可以使用 thenApply 方法來把這兩個線程串行化。

//多個任務串行執行,第二個任務依賴第一個任務的結果。

private static void thenApply() throws Exception {

CompletableFuture future = CompletableFuture.supplyAsync(() -> {

long result = new Random().nextInt(100);

System.out.println("result1=" + result);

return result;

}

).thenApply((t -> {

long result = t * 5;

System.out.println("result2=" + result);

return result;

}));

//方式一:阻塞等待結果

long result = future.get();

System.out.println("result2: " + result);

//方式二:調用成功后接收任務的處理結果,并消費處理,無返回結果

future.thenAccept((r) -> {

System.out.println("result2: " + r);

});

}

}

輸出:

result1=41

result2=205

result2: 205

result2: 205

handle 方法——可以處理正常和異常情況的thenApply 方法

handle 是執行任務完成時對結果的處理。

handle 方法和 thenApply 方法處理方式基本一樣。不同的是 handle 是在任務完成后再執行,還可以處理異常的任務。thenApply 只可以執行正常的任務,任務出現異常則不執行 thenApply 方法。

public CompletionStage handle(BiFunction super T, Throwable, ? extends U> fn);

public CompletionStage handleAsync(BiFunction super T, Throwable, ? extends U> fn);

public CompletionStage handleAsync(BiFunction super T, Throwable, ? extends U> fn,Executor executor);

示例:在 handle 中可以根據任務是否有異常來進行做相應的后續處理操作。而 thenApply 方法,如果上個任務出現錯誤,則不會執行 thenApply 方法。

public class CompletableFutureTest3 {

public static void main(String[] args) throws Exception {

CompletableFutureTest3.handle();

}

public static void handle() throws Exception {

CompletableFuture future = CompletableFuture.supplyAsync(new Supplier() {

@Override

public Integer get() {

int i = 10 / 0;

return new Random().nextInt(10);

}

}).handle(

(param, throwable) -> {

int result = -1;

if (throwable == null) {

result = param * 2;

} else {

System.out.println(throwable.getMessage());

}

return result;

}

/*new BiFunction() {

@Override

public Integer apply(Integer param, Throwable throwable) {

int result = -1;

if(throwable==null){

result = param * 2;

}else{

System.out.println(throwable.getMessage());

}

return result;

}

}*/);

System.out.println(future.get());

}

}

輸出:

java.lang.ArithmeticException: / by zero

-1

thenAccept 消費處理結果——無返回結果

接收任務的處理結果,并消費處理,無返回結果。

public CompletionStage thenAccept(Consumer super T> action);

public CompletionStage thenAcceptAsync(Consumer super T> action);

public CompletionStage thenAcceptAsync(Consumer super T> action,Executor executor);

示例:

public class CompletableFutureTest3 {

public static void main(String[] args) throws Exception {

//CompletableFutureTest3.handle();

CompletableFutureTest3.thenAccept();

}

public static void thenAccept() throws Exception {

CompletableFuture future = CompletableFuture.supplyAsync(() -> {

return new Random().nextInt(10);

}

).thenAccept(integer -> {

System.out.println(integer);

});

future.get();

}

}

//輸出:5

thenRun 方法——繼續執行下一個Runnable任務,不獲取上一個任務的處理結果

跟 thenAccept 方法不一樣的是,不關心任務的處理結果。只要上面的任務執行完成,就開始執行 thenRun 。

public CompletionStage thenRun(Runnable action);

public CompletionStage thenRunAsync(Runnable action);

public CompletionStage thenRunAsync(Runnable action,Executor executor);

示例:

public class CompletableFutureTest3 {

public static void main(String[] args) throws Exception {

CompletableFutureTest3.thenRun();

}

public static void thenRun() throws Exception{

CompletableFuture future = CompletableFuture.supplyAsync(new Supplier() {

@Override

public Integer get() {

try {

TimeUnit.SECONDS.sleep(2);

} catch (InterruptedException e) {

e.printStackTrace();

}

return new Random().nextInt(10);

}

}).thenRun(() -> {

System.out.println("thenRun ...");

});

future.get();

}

}

//2秒后輸出:thenRun ...

thenCombine 合并任務

thenCombine 會把 兩個 CompletionStage 的任務都執行完成后,把兩個任務的結果一塊交給 thenCombine 來處理。

public CompletionStage thenCombine(CompletionStage extends U> other,BiFunction super T,? super U,? extends V> fn);

public CompletionStage thenCombineAsync(CompletionStage extends U> other,BiFunction super T,? super U,? extends V> fn);

public CompletionStage thenCombineAsync(CompletionStage extends U> other,BiFunction super T,? super U,? extends V> fn,Executor executor);

示例:

public class CompletableFutureTest3 {

public static void main(String[] args) throws Exception {

CompletableFutureTest3.thenCombine();

}

private static void thenCombine() throws Exception {

CompletableFuture future1 = CompletableFuture.supplyAsync(() -> {

return "hello";

});

CompletableFuture future2 = CompletableFuture.supplyAsync(() -> {

return "world";

});

CompletableFuture result = future1.thenCombine(future2, (result1, result2) -> {

return result1 + " " + result2;

});

System.out.println(result.get());

}

}

//輸出:hello world

thenAcceptBoth

當兩個CompletionStage都執行完成后,把結果一塊交給thenAcceptBoth來進行消耗。

public CompletionStage thenAcceptBoth(CompletionStage extends U> other,BiConsumer super T, ? super U> action);

public CompletionStage thenAcceptBothAsync(CompletionStage extends U> other,BiConsumer super T, ? super U> action);

public CompletionStage thenAcceptBothAsync(CompletionStage extends U> other,BiConsumer super T, ? super U> action, Executor executor);

示例:

public class CompletableFutureTest3 {

public static void main(String[] args) throws Exception {

CompletableFutureTest3.thenAcceptBoth();

//等待守護進程執行完

TimeUnit.SECONDS.sleep(5);

}

private static void thenAcceptBoth() throws Exception {

CompletableFuture f1 = CompletableFuture.supplyAsync(() -> {

int t = new Random().nextInt(3);

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("f1=" + t);

return t;

});

CompletableFuture f2 = CompletableFuture.supplyAsync(() -> {

int t = new Random().nextInt(3);

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("f2=" + t);

return t;

});

f1.thenAcceptBoth(f2, (result1, result2) -> {

System.out.println("f1=" + result1 + ";f2=" + result2 + ";");

});

}

}

輸出:

f1=1

f2=1

f1=1;f2=1;

applyToEither 方法——有返回值消耗

兩個CompletionStage,誰執行返回的結果快,我就用那個CompletionStage的結果進行下一步的轉化操作。

public CompletionStage applyToEither(CompletionStage extends T> other,Function super T, U> fn);

public CompletionStage applyToEitherAsync(CompletionStage extends T> other,Function super T, U> fn);

public CompletionStage applyToEitherAsync(CompletionStage extends T> other,Function super T, U> fn,Executor executor);

示例:

public class CompletableFutureTest3 {

public static void main(String[] args) throws Exception {

CompletableFutureTest3.applyToEither();

}

private static void applyToEither() throws Exception {

CompletableFuture f1 = CompletableFuture.supplyAsync(()->{

int t = 1;

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("f1="+t);

return t;

});

CompletableFuture f2 = CompletableFuture.supplyAsync(()->{

int t = 2;

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("f2="+t);

return t;

});

CompletableFuture result = f1.applyToEither(f2, (r)->{

System.out.println(r);

return r * 2;

});

System.out.println(result.get());

}

輸出:

f1=1

1

2

acceptEither 方法——無返回值消耗

兩個CompletionStage,誰執行返回的結果快,我就用那個CompletionStage的結果進行下一步的消耗操作。注意,這時候其實兩個CompletionStage都是會執行完的,只是我們只獲取其中的一個比較快的結果而已,參考示例的輸出。

public CompletionStage acceptEither(CompletionStage extends T> other,Consumer super T> action);

public CompletionStage acceptEitherAsync(CompletionStage extends T> other,Consumer super T> action);

public CompletionStage acceptEitherAsync(CompletionStage extends T> other,Consumer super T> action,Executor executor);

示例:

public class CompletableFutureTest3 {

public static void main(String[] args) throws Exception {

//CompletableFutureTest3.applyToEither();

CompletableFutureTest3.acceptEither();

TimeUnit.SECONDS.sleep(5);

}

private static void acceptEither() throws Exception {

CompletableFuture f1 = CompletableFuture.supplyAsync(() -> {

int t = new Random().nextInt(3);

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("f1=" + t);

return t;

});

CompletableFuture f2 = CompletableFuture.supplyAsync(() -> {

int t = new Random().nextInt(3);

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("f2=" + t);

return t;

});

f1.acceptEither(f2, (t) -> {

System.out.println(t);

});

}

}

輸出:

f1=1

1

f2=2

runAfterEither 方法

兩個CompletionStage,任何一個完成了都會執行下一步的操作(Runnable),兩個CompletionStage都是會執行完的.

public CompletionStage runAfterEither(CompletionStage> other,Runnable action);

public CompletionStage runAfterEitherAsync(CompletionStage> other,Runnable action);

public CompletionStage runAfterEitherAsync(CompletionStage> other,Runnable action,Executor executor);

示例代碼

public class CompletableFutureTest3 {

public static void main(String[] args) throws Exception {

//CompletableFutureTest3.applyToEither();

//CompletableFutureTest3.acceptEither();

CompletableFutureTest3.runAfterEither();

TimeUnit.SECONDS.sleep(5);

}

private static void runAfterEither() throws Exception {

CompletableFuture f1 = CompletableFuture.supplyAsync(new Supplier() {

@Override

public Integer get() {

int t = new Random().nextInt(3);

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("f1=" + t);

return t;

}

});

CompletableFuture f2 = CompletableFuture.supplyAsync(new Supplier() {

@Override

public Integer get() {

int t = new Random().nextInt(3);

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("f2=" + t);

return t;

}

});

f1.runAfterEither(f2, ()->{

System.out.println("上面有一個已經完成了。");

});

}

}

輸出:

f1=0

上面有一個已經完成了。

f2=1

runAfterBoth

兩個CompletionStage,都完成了計算才會執行下一步的操作(Runnable),注意輸出順序,runAfterBoth方法要等兩個CompletionStage都執行完了才會執行。

public CompletionStage runAfterBoth(CompletionStage> other,Runnable action);

public CompletionStage runAfterBothAsync(CompletionStage> other,Runnable action);

public CompletionStage runAfterBothAsync(CompletionStage> other,Runnable action,Executor executor);

示例代碼

public class CompletableFutureTest3 {

public static void main(String[] args) throws Exception {

//CompletableFutureTest3.applyToEither();

//CompletableFutureTest3.acceptEither();

//CompletableFutureTest3.runAfterEither();

CompletableFutureTest3.runAfterBoth();

TimeUnit.SECONDS.sleep(5);

}

private static void runAfterBoth() throws Exception {

CompletableFuture f1 = CompletableFuture.supplyAsync(new Supplier() {

@Override

public Integer get() {

int t = new Random().nextInt(3);

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("f1="+t);

return t;

}

});

CompletableFuture f2 = CompletableFuture.supplyAsync(new Supplier() {

@Override

public Integer get() {

int t = new Random().nextInt(3);

try {

TimeUnit.SECONDS.sleep(t);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("f2="+t);

return t;

}

});

f1.runAfterBoth(f2, new Runnable() {

@Override

public void run() {

System.out.println("上面兩個任務都執行完成了。");

}

});

}

}

輸出:

f1=1

f2=2

上面兩個任務都執行完成了。

thenCompose 方法

thenCompose 方法允許你對兩個 CompletionStage 進行流水線操作,第一個操作完成時,將其結果作為參數傳遞給第二個操作。

public CompletableFuture thenCompose(Function super T, ? extends CompletionStage> fn);

public CompletableFuture thenComposeAsync(Function super T, ? extends CompletionStage> fn) ;

public CompletableFuture thenComposeAsync(Function super T, ? extends CompletionStage> fn, Executor executor) ;

示例代碼

public class CompletableFutureTest3 {

public static void main(String[] args) throws Exception {

CompletableFutureTest3.thenCompose();

TimeUnit.SECONDS.sleep(3);

}

private static void thenCompose() throws Exception {

CompletableFuture f = CompletableFuture.supplyAsync(() -> {

int t = new Random().nextInt(3);

System.out.println("t1=" + t);

return t;

}).thenCompose((param) -> {

return CompletableFuture.supplyAsync(() -> {

int t = param * 2;

System.out.println("t2=" + t);

return t;

});

});

System.out.println("thenCompose result : " + f.get());

}

}

輸出:

t1=1

t2=2

thenCompose result : 2

疑問:

Q:thenAcceptBoth與thenCombine 的區別是什么?

A:thenAcceptBoth無返回值消耗執行,thenCombine 會有返回值。一般accept都是沒有返回值的,apply是有返回值的。

Q:thenCompose 與thenApply 方法 的區別是什么?不都是串行執行下一個任務,并把第一個任務作為參數傳遞給第二個任務么?

獲取線程執行結果的6種方法

方式1:Thread的join()方法實現

代碼中通過join方式阻塞了當前主線程,當thread線程執行完畢之后,join方法才會繼續執行。

join的方式,只能阻塞一個線程,如果其他線程中也需要獲取thread線程的執行結果,join方法無能為力了。

示例:

public class ThreadJoinTest {

//用于封裝結果

static class Result {

T result;

public T getResult() {

return result;

}

public void setResult(T result) {

this.result = result;

}

}

public static void main(String[] args) throws InterruptedException {

Result result = new Result<>();

Thread t = new Thread(() -> {

System.out.println("start thread!");

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

result.setResult("success");

System.out.println("end thread!");

});

t.start();

//讓主線程等待thread線程執行完畢之后再繼續,join方法會讓當前線程阻塞

t.join();

System.out.println("main get result="+result.getResult());

}

}

輸出:

start thread!

end thread!

main get result=success

方式2:CountDownLatch實現

使用CountDownLatch可以讓一個或者多個線程等待一批線程完成之后,自己再繼續.

示例:

public class CountDownLatchTest2 {

static class Result{

private T result;

public T getResult() {

return result;

}

public void setResult(T result) {

this.result = result;

}

}

public static void main(String[] args) throws InterruptedException {

Result result = new Result<>();

CountDownLatch latch = new CountDownLatch(1);

Thread t = new Thread(() -> {

System.out.println("start thread!");

try {

TimeUnit.SECONDS.sleep(1);

result.setResult("success");

System.out.println("end thread!");

} catch (InterruptedException e) {

e.printStackTrace();

}finally {

latch.countDown();

}

});

t.start();

latch.await();

System.out.println("main get result="+result.getResult());

}

}

輸出:

start thread!

end thread!

main get result=success

方式3:ExecutorService.submit方法實現——ThreadPoolExecutor

使用ExecutorService.submit方法實現的,此方法返回一個Future,future.get()會讓當前線程阻塞,直到Future關聯的任務執行完畢。

示例:

public class ThreadPoolExecutorTest2 {

public static void main(String[] args) throws ExecutionException, InterruptedException {

//自定義包含策略

ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 5, 60,

TimeUnit.SECONDS, new LinkedBlockingQueue<>(5),

new DemoThreadFactory("訂單創建組"), new ThreadPoolExecutor.AbortPolicy());

Future future = executor.submit(() -> {

System.out.println("start thread!");

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("end thread!");

return "success";

});

executor.shutdown();

System.out.println("main get result="+future.get());

}

}

輸出同上。

方式4:FutureTask方式1——作為Runnable傳給Thread執行

線程池的submit方法傳入的Callable對象本質上也是包裝成一個FutureTask來執行。

代碼中使用FutureTask實現的,FutureTask實現了Runnable接口,并且內部帶返回值,所以可以傳遞給Thread直接運行,futureTask.get()會阻塞當前線程,直到FutureTask構造方法傳遞的任務執行完畢,get方法才會返回。

示例:

public class FutureTaskTest {

public static void main(String[] args) throws ExecutionException, InterruptedException {

//創建一個FutureTask

FutureTask futureTask = new FutureTask<>(() -> {

System.out.println("start thread!");

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("end thread!");

return "success";

});

//將futureTask傳遞一個線程運行

new Thread(futureTask).start();

//futureTask.get()會阻塞當前線程,直到futureTask執行完畢

String result = futureTask.get();

System.out.println("main get result=" + result);

}

}

方式5:FutureTask方式2——構造FutureTask對象及執行內容,直接在Thread里面跑run方法

當futureTask的run()方法執行完畢之后,futureTask.get()會從阻塞中返回。

示例:

public class FutureTaskTest1 {

public static void main(String[] args) throws ExecutionException, InterruptedException {

//創建一個FutureTask

FutureTask futureTask = new FutureTask<>(() -> {

System.out.println("start thread!");

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("end thread!");

return "success";

});

//將futureTask傳遞一個線程運行

new Thread(()->futureTask.run()).start();

//futureTask.get()會阻塞當前線程,直到futureTask執行完畢

String result = futureTask.get();

System.out.println("main get result=" + result);

}

}

方式6:CompletableFuture方式實現

CompletableFuture.supplyAsync可以用來異步執行一個帶返回值的任務,調用completableFuture.get()

會阻塞當前線程,直到任務執行完畢,get方法才會返回。

public class CompletableFutureTest4 {

public static void main(String[] args) throws Exception {

CompletableFuture future = CompletableFuture.supplyAsync(() -> {

System.out.println("start thread!");

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("end thread!");

return "success";

});

// future.get()會阻塞當前線程直到獲得結果

System.out.println("main get result="+future.get());

}

}

高并發中計數器的四種實現方式

需求:一個jvm中實現一個計數器功能,需保證多線程情況下數據正確性。

我們來模擬50個線程,每個線程對計數器遞增100萬次,最終結果應該是5000萬。

我們使用4種方式實現,看一下其性能,然后引出為什么需要使用LongAdder、LongAccumulator。

方式一:使用加鎖的方式實現——synchronized或Lock

從示例輸出結果看,ReentrantLock的效率明顯比synchronized差了2-3倍。

示例:

public class SynchronizeCalculator {

private static long count = 0;

private static Lock lock = new ReentrantLock();

public synchronized static void incrment() {

count++;

}

public static void incrmentByLock() {

lock.lock();

try {

count++;

}finally {

lock.unlock();

}

}

public static void main(String[] args) throws InterruptedException {

for (int i = 0; i < 5; i++) {

count = 0;

averageTest();

}

}

public static void averageTest() throws InterruptedException {

long t1 = System.currentTimeMillis();

//自定義包含策略

ThreadPoolExecutor executor = new ThreadPoolExecutor(50, 50, 60,

TimeUnit.SECONDS, new LinkedBlockingQueue<>(5),

new DemoThreadFactory("訂單創建組"), new ThreadPoolExecutor.AbortPolicy());

CountDownLatch latch = new CountDownLatch(50);

for (int i = 0; i < 50; i++) {

executor.execute(() -> {

try {

for (int j = 0; j < 1000000; j++) {

incrment();

//incrmentByLock();

}

} finally {

latch.countDown();

}

});

}

latch.await();

long t2 = System.currentTimeMillis();

System.out.println(String.format("結果:%s,耗時(ms):%s", count, (t2 - t1)));

executor.shutdown();

}

}

輸出:

//synchronized

結果:50000000,耗時(ms):490

結果:50000000,耗時(ms):1574

結果:50000000,耗時(ms):399

結果:50000000,耗時(ms):395

結果:50000000,耗時(ms):396

//lock

結果:50000000,耗時(ms):1289

結果:50000000,耗時(ms):1239

結果:50000000,耗時(ms):1224

結果:50000000,耗時(ms):1219

結果:50000000,耗時(ms):1246

方式2:AtomicLong實現

AtomicLong內部采用CAS的方式實現,并發量大的情況下,CAS失敗率比較高,導致性能比synchronized還低一些。并發量不是太大的情況下,CAS性能還是可以的。

示例:

public class AtomicLongTest {

private static AtomicLong count = new AtomicLong(0);

public static void main(String[] args) throws InterruptedException {

for (int i = 0; i < 5; i++) {

count.set(0);

averageTest();

}

}

public static void averageTest() throws InterruptedException {

long t1 = System.currentTimeMillis();

//自定義包含策略

ThreadPoolExecutor executor = new ThreadPoolExecutor(50, 50, 60,

TimeUnit.SECONDS, new LinkedBlockingQueue<>(5),

new DemoThreadFactory("訂單創建組"), new ThreadPoolExecutor.AbortPolicy());

CountDownLatch latch = new CountDownLatch(50);

for (int i = 0; i < 50; i++) {

executor.execute(() -> {

try {

for (int j = 0; j < 1000000; j++) {

count.getAndIncrement();

}

} finally {

latch.countDown();

}

});

}

latch.await();

long t2 = System.currentTimeMillis();

System.out.println(String.format("結果:%s,耗時(ms):%s", count.get(), (t2 - t1)));

executor.shutdown();

}

}

輸出:

結果:50000000,耗時(ms):1018

結果:50000000,耗時(ms):1442

結果:50000000,耗時(ms):1033

結果:50000000,耗時(ms):935

結果:50000000,耗時(ms):1320

方式3:LongAdder實現——相當于鎖分段技術

先介紹一下LongAdder,說到LongAdder,不得不提的就是AtomicLong,AtomicLong是JDK1.5開始出現的,里面主要使用了一個long類型的value作為成員變量,然后使用循環的CAS操作去操作value的值,并發量比較大的情況下,CAS操作失敗的概率較高,內部失敗了會重試,導致耗時可能會增加。

LongAdder是JDK1.8開始出現的,所提供的API基本上可以替換掉原先的AtomicLong。LongAdder在并發量比較大的情況下,操作數據的時候,相當于把這個數字分成了很多份數字,然后交給多個人去管控,每個管控者負責保證部分數字在多線程情況下操作的正確性。當多線程訪問的時,通過hash算法映射到具體管控者去操作數據,最后再匯總所有的管控者的數據,得到最終結果。相當于降低了并發情況下鎖的粒度,所以效率比較高,看一下下面的圖,方便理解:

示例:

代碼中new LongAdder()創建一個LongAdder對象,內部數字初始值是0,調用increment()方法可以對LongAdder內部的值原子遞增1。reset()方法可以重置LongAdder的值,使其歸0。

public class LongAdderTest {

private static LongAdder count = new LongAdder();

public static void main(String[] args) throws InterruptedException {

for (int i = 0; i < 5; i++) {

count.reset();

averageTest();

}

}

public static void averageTest() throws InterruptedException {

long t1 = System.currentTimeMillis();

//自定義包含策略

ThreadPoolExecutor executor = new ThreadPoolExecutor(50, 50, 60,

TimeUnit.SECONDS, new LinkedBlockingQueue<>(5),

new DemoThreadFactory("訂單創建組"), new ThreadPoolExecutor.AbortPolicy());

CountDownLatch latch = new CountDownLatch(50);

for (int i = 0; i < 50; i++) {

executor.execute(() -> {

try {

for (int j = 0; j < 1000000; j++) {

count.increment();

}

} finally {

latch.countDown();

}

});

}

latch.await();

long t2 = System.currentTimeMillis();

System.out.println(String.format("結果:%s,耗時(ms):%s", count.sum(), (t2 - t1)));

executor.shutdown();

}

}

輸出:

結果:50000000,耗時(ms):209

結果:50000000,耗時(ms):133

結果:50000000,耗時(ms):149

結果:50000000,耗時(ms):146

結果:50000000,耗時(ms):148

方式4:LongAccumulator實現

LongAccumulator介紹

LongAccumulator是LongAdder的功能增強版。LongAdder的API只有對數值的加減,而LongAccumulator提供了自定義的函數操作,其構造函數如下:

/**

* accumulatorFunction:需要執行的二元函數(接收2個long作為形參,并返回1個long)

* identity:初始值

**/

public LongAccumulator(LongBinaryOperator accumulatorFunction, long identity) {

this.function = accumulatorFunction;

base = this.identity = identity;

}

示例:

LongAccumulator的效率和LongAdder差不多,不過更靈活一些。

調用new LongAdder()等價于new LongAccumulator((x, y) -> x + y, 0L)。

從上面4個示例的結果來看,LongAdder、LongAccumulator全面超越同步鎖及AtomicLong的方式,建議在使用AtomicLong的地方可以直接替換為LongAdder、LongAccumulator,吞吐量更高一些。

public class LongAccumulatorTest {

private static volatile LongAccumulator count = new LongAccumulator((x, y) -> x + y, 0);

public static void main(String[] args) throws InterruptedException {

for (int i = 0; i < 5; i++) {

count.reset();

averageTest();

}

}

public static void averageTest() throws InterruptedException {

long t1 = System.currentTimeMillis();

//自定義包含策略

ThreadPoolExecutor executor = new ThreadPoolExecutor(50, 50, 60,

TimeUnit.SECONDS, new LinkedBlockingQueue<>(5),

new DemoThreadFactory("訂單創建組"), new ThreadPoolExecutor.AbortPolicy());

CountDownLatch latch = new CountDownLatch(50);

for (int i = 0; i < 50; i++) {

executor.execute(() -> {

try {

for (int j = 0; j < 1000000; j++) {

count.accumulate(1);

}

} finally {

latch.countDown();

}

});

}

latch.await();

long t2 = System.currentTimeMillis();

System.out.println(String.format("結果:%s,耗時(ms):%s", count.longValue(), (t2 - t1)));

executor.shutdown();

}

}

輸出:

結果:50000000,耗時(ms):152

結果:50000000,耗時(ms):148

結果:50000000,耗時(ms):137

結果:50000000,耗時(ms):137

結果:50000000,耗時(ms):144

疑問:

Q:LongAccumulator.reset方法并不能重置重置LongAccumulator的identity:初始值正確,使其恢復原來的初始值。當初始值為0是不會發生這個問題,而當我們設置初始值如1時,就會導致后續的計算操作增加了5份初始值,目前猜測原因是因為代碼中LongAccumulator在并發量比較大的情況下,操作數據的時候,相當于把這個數字分成了很多份數字 ,而初始化的時候也是初始化了多份數據,導致初始值疊加了多份。不知道這是個bug么?待解惑。

在此記錄下來希望有遇到這種情況的同學注意。解決方法便是要么初始值identity=0不會有這種問題;或者有需要使用reset方法重置的改為重新創建個LongAccumulator處理。

源碼:

public void reset() {

Cell[] as = cells; Cell a;

base = identity;

if (as != null) {

for (int i = 0; i < as.length; ++i) {

if ((a = as[i]) != null)

//對多個cell進行初始值賦值導致后面計算疊加了多份初始值

a.value = identity;

}

}

}

示例:

public class LongAccumulatorTest {

//設置初始值為1查看輸出結果

private static volatile LongAccumulator count = new LongAccumulator((x, y) -> x + y, 1);

public static void main(String[] args) throws InterruptedException {

for (int i = 0; i < 5; i++) {

count.reset();

averageTest();

}

}

public static void averageTest() throws InterruptedException {

long t1 = System.currentTimeMillis();

//自定義包含策略

ThreadPoolExecutor executor = new ThreadPoolExecutor(50, 50, 60,

TimeUnit.SECONDS, new LinkedBlockingQueue<>(5),

new DemoThreadFactory("訂單創建組"), new ThreadPoolExecutor.AbortPolicy());

CountDownLatch latch = new CountDownLatch(50);

for (int i = 0; i < 50; i++) {

executor.execute(() -> {

try {

for (int j = 0; j < 1000000; j++) {

count.accumulate(1);

}

} finally {

latch.countDown();

}

});

}

latch.await();

long t2 = System.currentTimeMillis();

System.out.println(String.format("結果:%s,耗時(ms):%s", count.longValue(), (t2 - t1)));

executor.shutdown();

}

}

輸出:這時候你會發現只有第一次計算是正確的,只要使用了rest方法重置就會導致這個錯誤。

結果:50000001,耗時(ms):185

結果:50000005,耗時(ms):143

結果:50000005,耗時(ms):139

結果:50000005,耗時(ms):162

結果:50000005,耗時(ms):142

演示公平鎖和非公平鎖

先理解一下什么是公平鎖、非公平鎖?

公平鎖和非公平鎖體現在別人釋放鎖的一瞬間,如果前面已經有排隊的,新來的是否可以插隊,如果可以插隊表示是非公平的,如果不可用插隊,只能排在最后面,是公平的方式。

示例:

@Slf4j

public class ReentrantLockTest2 {

public static void main(String[] args) throws InterruptedException {

ReentrantLockTest2.LockTest(false);

TimeUnit.SECONDS.sleep(4);

log.error("-------------------------------");

ReentrantLockTest2.LockTest(true);

}

public static void LockTest(boolean fair) throws InterruptedException {

ReentrantLock lock = new ReentrantLock(fair);

new Thread(() -> {

lock.lock();

try {

log.error(Thread.currentThread().getName() + " start!");

TimeUnit.SECONDS.sleep(3);

new Thread(() -> {

//注意線程池要當前線程創建的才能使用,如果傳給新開的線程會獲取不到線程池

test("后到組",lock);

}).start();

//test(executorAfter,lock);

log.error(Thread.currentThread().getName() + "end!");

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

lock.unlock();

}

}, "Hold Lock 4 Test Thread").start();

test("先到組",lock);

TimeUnit.SECONDS.sleep(3);

}

private static void test(String name,Lock lock){

//自定義包含策略

ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 60,

TimeUnit.SECONDS, new LinkedBlockingQueue<>(5),

new DemoThreadFactory(name), new ThreadPoolExecutor.AbortPolicy());

for (int i = 0; i < 10; i++) {

executor.execute(() -> {

lock.lock();

try {

log.error("獲取到鎖!");

} finally {

lock.unlock();

}

});

}

executor.shutdown();

}

}

輸出:

14:45:23.204 [Hold Lock 4 Test Thread] ERROR com.self.current.ReentrantLockTest2 - Hold Lock 4 Test Thread start!

14:45:26.211 [Hold Lock 4 Test Thread] ERROR com.self.current.ReentrantLockTest2 - Hold Lock 4 Test Threadend!

14:45:26.211 [From DemoThreadFactory's 先到組-Worker-1] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.211 [From DemoThreadFactory's 先到組-Worker-2] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.212 [From DemoThreadFactory's 先到組-Worker-3] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.212 [From DemoThreadFactory's 先到組-Worker-4] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.212 [From DemoThreadFactory's 先到組-Worker-5] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.212 [From DemoThreadFactory's 先到組-Worker-6] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.212 [From DemoThreadFactory's 先到組-Worker-7] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.212 [From DemoThreadFactory's 先到組-Worker-8] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.212 [From DemoThreadFactory's 后到組-Worker-4] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.212 [From DemoThreadFactory's 先到組-Worker-9] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.213 [From DemoThreadFactory's 后到組-Worker-8] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.218 [From DemoThreadFactory's 后到組-Worker-10] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.218 [From DemoThreadFactory's 先到組-Worker-10] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.218 [From DemoThreadFactory's 后到組-Worker-2] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.218 [From DemoThreadFactory's 后到組-Worker-1] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.219 [From DemoThreadFactory's 后到組-Worker-3] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.219 [From DemoThreadFactory's 后到組-Worker-5] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.219 [From DemoThreadFactory's 后到組-Worker-6] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.219 [From DemoThreadFactory's 后到組-Worker-7] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:26.219 [From DemoThreadFactory's 后到組-Worker-9] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:30.205 [main] ERROR com.self.current.ReentrantLockTest2 - -------------------------------

14:45:30.205 [Hold Lock 4 Test Thread] ERROR com.self.current.ReentrantLockTest2 - Hold Lock 4 Test Thread start!

14:45:33.206 [Hold Lock 4 Test Thread] ERROR com.self.current.ReentrantLockTest2 - Hold Lock 4 Test Threadend!

14:45:33.206 [From DemoThreadFactory's 先到組-Worker-1] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.206 [From DemoThreadFactory's 先到組-Worker-2] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.209 [From DemoThreadFactory's 先到組-Worker-3] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.209 [From DemoThreadFactory's 先到組-Worker-4] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.209 [From DemoThreadFactory's 先到組-Worker-5] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.209 [From DemoThreadFactory's 先到組-Worker-6] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.210 [From DemoThreadFactory's 先到組-Worker-7] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.210 [From DemoThreadFactory's 先到組-Worker-8] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.210 [From DemoThreadFactory's 先到組-Worker-9] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.210 [From DemoThreadFactory's 先到組-Worker-10] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.210 [From DemoThreadFactory's 后到組-Worker-2] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.210 [From DemoThreadFactory's 后到組-Worker-1] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.211 [From DemoThreadFactory's 后到組-Worker-6] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.211 [From DemoThreadFactory's 后到組-Worker-7] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.211 [From DemoThreadFactory's 后到組-Worker-5] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.211 [From DemoThreadFactory's 后到組-Worker-4] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.211 [From DemoThreadFactory's 后到組-Worker-3] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.211 [From DemoThreadFactory's 后到組-Worker-9] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.212 [From DemoThreadFactory's 后到組-Worker-10] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

14:45:33.212 [From DemoThreadFactory's 后到組-Worker-8] ERROR com.self.current.ReentrantLockTest2 - 獲取到鎖!

google提供的一些好用的并發工具類

關于并發方面的,juc已幫我們提供了很多好用的工具,而谷歌在此基礎上做了擴展,使并發編程更容易,這些工具放在guava.jar包中。

guava maven配置

com.google.guava

guava

27.0-jre

guava中常用幾個類

MoreExecutors:提供了一些靜態方法,是對juc中的Executors類的一個擴展。

Futures:也提供了很多靜態方法,是對juc中Future的一個擴展。

案例1:異步執行任務完畢之后回調——相當于CompletableFuture的whenComplete方法

ListeningExecutorService接口繼承于juc中的ExecutorService接口,對ExecutorService做了一些擴展,看其名字中帶有Listening,說明這個接口自帶監聽的功能,可以監聽異步執行任務的結果。通過MoreExecutors.listeningDecorator創建一個ListeningExecutorService對象,需傳遞一個ExecutorService參數,傳遞的ExecutorService負責異步執行任務。

ListeningExecutorService的submit方法用來異步執行一個任務,返回ListenableFuture,ListenableFuture接口繼承于juc中的Future接口,對Future做了擴展,使其帶有監聽的功能。調用submit.addListener可以在執行的任務上添加監聽器,當任務執行完畢之后會回調這個監聽器中的方法。

ListenableFuture的get方法會阻塞當前線程直到任務執行完畢。

另一種回調方式是通過調用Futures的靜態方法addCallback在異步執行的任務中添加回調,回調的對象是一個FutureCallback,此對象有2個方法,任務執行成功調用onSuccess,執行失敗調用onFailure。

失敗的情況可以將代碼中int i = 10 / 0;注釋去掉,執行一下可以看看效果。

示例:

@Slf4j

public class GuavaTest {

//相當于CompletableFuture的whenComplete方法

public static void main1(String[] args) throws ExecutionException, InterruptedException {

//創建一個線程池

ExecutorService delegate = Executors.newFixedThreadPool(5);

try {

ListeningExecutorService executorService = MoreExecutors.listeningDecorator(delegate);

//異步執行一個任務

ListenableFuture submit = executorService.submit(() -> {

log.error("{}", System.currentTimeMillis());

//休眠2秒,默認耗時

TimeUnit.SECONDS.sleep(2);

log.error("{}", System.currentTimeMillis());

return 10;

});

//當任務執行完畢之后回調對應的方法

submit.addListener(() -> {

log.error("任務執行完畢了,我被回調了");

}, MoreExecutors.directExecutor());

log.error("{}", submit.get());

} finally {

delegate.shutdown();

}

}

//相當于CompletableFuture的whenComplete方法

public static void main(String[] args) throws ExecutionException, InterruptedException {

ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 60,

TimeUnit.SECONDS, new LinkedBlockingQueue<>(10),

new DemoThreadFactory("訂單創建組"), new ThreadPoolExecutor.AbortPolicy());

ListeningExecutorService service = MoreExecutors.listeningDecorator(executor);

try {

ListenableFuture future = service.submit(() -> {

log.error("{}", System.currentTimeMillis());

//休眠2秒,默認耗時

TimeUnit.SECONDS.sleep(2);

//int i = 10 / 0;

log.error("{}", System.currentTimeMillis());

return 10;

});

Futures.addCallback(future, new FutureCallback() {

@Override

public void onSuccess(Integer integer) {

log.error("執行成功:{}", integer);

}

@Override

public void onFailure(Throwable throwable) {

log.error("執行失敗:{}", throwable.getMessage());

}

});

log.error("{}", future.get());

} finally {

service.shutdown();

}

}

}

輸出:

15:32:54.480 [From DemoThreadFactory's 訂單創建組-Worker-1] ERROR com.self.current.GuavaTest - 1599809574477

15:32:56.487 [From DemoThreadFactory's 訂單創建組-Worker-1] ERROR com.self.current.GuavaTest - 1599809576487

15:32:56.488 [main] ERROR com.self.current.GuavaTest - 10

15:32:56.488 [From DemoThreadFactory's 訂單創建組-Worker-1] ERROR com.self.current.GuavaTest - 執行成功:10

示例2:獲取一批異步任務的執行結果——Futures.allAsList(futureList).get()

結果中按順序輸出了6個異步任務的結果,此處用到了Futures.allAsList方法,看一下此方法的聲明:

public static ListenableFuture> allAsList(

Iterable extends ListenableFuture extends V>> futures)

傳遞一批ListenableFuture,返回一個ListenableFuture>,內部將一批結果轉換為了一個ListenableFuture對象。

示例:

public static void main(String[] args) throws ExecutionException, InterruptedException {

log.error("star");

ExecutorService delegate = Executors.newFixedThreadPool(5);

try {

ListeningExecutorService executorService = MoreExecutors.listeningDecorator(delegate);

List> futureList = new ArrayList<>();

for (int i = 5; i >= 0; i--) {

int j = i;

futureList.add(executorService.submit(() -> {

TimeUnit.SECONDS.sleep(j);

return j;

}));

}

//把多個ListenableFuture轉換為一個ListenableFuture

//ListenableFuture> listListenableFuture = Futures.allAsList(futureList);

//獲取一批任務的執行結果

List resultList = Futures.allAsList(futureList).get();

//輸出

resultList.forEach(item -> {

log.error("{}", item);

});

} finally {

delegate.shutdown();

}

}

輸出:

15:45:51.160 [main] ERROR com.self.current.GuavaTest - star

15:45:56.185 [main] ERROR com.self.current.GuavaTest - 5

15:45:56.185 [main] ERROR com.self.current.GuavaTest - 4

15:45:56.185 [main] ERROR com.self.current.GuavaTest - 3

15:45:56.185 [main] ERROR com.self.current.GuavaTest - 2

15:45:56.185 [main] ERROR com.self.current.GuavaTest - 1

15:45:56.185 [main] ERROR com.self.current.GuavaTest - 0

示例3:一批任務異步執行完畢之后回調——包裝futureList傳遞給Futures.addCallback 方法

異步執行一批任務,最后計算其和,代碼中異步執行了一批任務,所有任務完成之后,回調了上面的onSuccess方法,內部對所有的結果進行sum操作。

示例:

public static void main(String[] args) throws ExecutionException, InterruptedException {

log.error("start");

ExecutorService delegate = Executors.newFixedThreadPool(5);

try {

ListeningExecutorService executorService = MoreExecutors.listeningDecorator(delegate);

List> futureList = new ArrayList<>();

for (int i = 5; i >= 0; i--) {

int j = i;

futureList.add(executorService.submit(() -> {

TimeUnit.SECONDS.sleep(j);

return j;

}));

}

//把多個ListenableFuture轉換為一個ListenableFuture

ListenableFuture> listListenableFuture = Futures.allAsList(futureList);

Futures.addCallback(listListenableFuture, new FutureCallback>() {

@Override

public void onSuccess(List result) {

log.error("result中所有結果之和:"+result.stream().reduce(Integer::sum).get());

}

@Override

public void onFailure(Throwable throwable) {

log.error("執行任務發生異常:" + throwable.getMessage(), throwable);

}

});

} finally {

delegate.shutdown();

}

}

輸出:

15:57:00.539 [main] ERROR com.self.current.GuavaTest - start

15:57:05.560 [pool-2-thread-1] ERROR com.self.current.GuavaTest - result中所有結果之和:15

其他疑問:

Q:運行下面這個例子結束不了,debug倒是可以,這是為什么呢?Thread[Monitor Ctrl-Break,5,main]是哪來的?

public class VolatileTest1 {

public static volatile int num = 0;

public static void add(){

num++;

}

public static void main(String[] args) throws InterruptedException {

Thread[] threads = new Thread[10];

for (Thread thread : threads) {

thread = new Thread(()->{

for (int i = 0; i < 1000; i++) {

VolatileTest1.add();

}

});

thread.start();

thread.join();

}

//2

//java.lang.ThreadGroup[name=main,maxpri=10]

// Thread[main,5,main]

// Thread[Monitor Ctrl-Break,5,main]

//結束不了,debug倒是可以,這是為什么呢?Thread[Monitor Ctrl-Break,5,main]是哪來的?

while (Thread.activeCount() >1){

Thread.yield();

System.out.println(Thread.activeCount());

ThreadGroup parent = Thread.currentThread().getThreadGroup();

parent.list();

}

System.out.println("num="+num);

}

}

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的java 检视_Java高并发系列——检视阅读(五)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

日产乱码一二三区别免费 | 精品国产一区二区三区四 | 黄色一区二区在线观看 | 国产一区二区久久 | 国产精品一区二区三区视频免费 | 毛片随便看 | 九九九九九精品 | 国产一级电影在线 | 91九色在线视频 | 国产免费嫩草影院 | 亚洲免费视频观看 | 中文字幕av一区二区三区四区 | 亚洲人成人天堂h久久 | 91九色性视频 | 91午夜精品 | 中文字幕国内精品 | 国产精品久久久久久久久软件 | 欧美国产精品久久久久久免费 | 久久久久久久久久久久av | 91在线观看视频 | 精品综合久久久 | 亚洲女欲精品久久久久久久18 | 视频在线一区二区三区 | 中文字幕一区二区三区视频 | 国产日产欧美在线观看 | 久久你懂的 | 日日操夜夜操狠狠操 | 91在线最新 | 国产精品一区电影 | 国产精品成人自产拍在线观看 | 婷婷精品国产欧美精品亚洲人人爽 | 国产精品综合在线 | 婷婷色在线资源 | 九九视频在线观看视频6 | 久久久久久国产精品999 | 91经典在线 | 丰满少妇在线观看资源站 | 亚洲精品国产精品乱码在线观看 | 在线观看精品视频 | 亚洲涩涩涩 | 久久久久久久久国产 | 玖玖在线观看视频 | 精品久久精品 | 成年人在线观看免费视频 | 91精品国产成人观看 | 欧美日韩高清一区二区三区 | 欧美在线观看小视频 | 婷婷久操 | 伊人色综合久久天天 | 成人一级电影在线观看 | 久久精品麻豆 | 正在播放 国产精品 | www.99在线观看 | 国产成人在线免费观看 | 九九热在线播放 | 黄色一级大片免费看 | 亚洲伦理电影在线 | 天天艹日日干 | 久久九九久久 | 国产一区视频导航 | 天天干婷婷| 婷婷精品视频 | 国产精品美女久久久久久久久久久 | 亚洲黄色成人网 | 久久久久久久久电影 | 97精品国自产拍在线观看 | 欧美综合久久 | 久草av在线播放 | 日韩精品久久久免费观看夜色 | 久久久穴 | 成年人国产精品 | 精品国产一区二区在线 | 亚洲高清久久久 | 婷婷丁香av| 99精品在线免费观看 | 婷婷视频导航 | 国产a级精品 | 久久久精品 | 亚洲精品电影在线 | 国产精品99免视看9 国产精品毛片一区视频 | 国产精品美女久久久久久 | 在线观看免费成人 | 在线 高清 中文字幕 | 亚洲精品免费视频 | 国产在线视频在线观看 | 国产丝袜美腿在线 | 丁香五婷 | 91精品国产自产91精品 | 亚洲精品国产精品国自产观看浪潮 | 中文乱幕日产无线码1区 | 久久久久激情视频 | 欧美特一级 | 婷婷在线资源 | 中文在线字幕免 | 久久亚洲电影 | 国产在线观看你懂得 | 97精品免费视频 | 日韩欧美一区二区三区在线观看 | 欧美在线一级片 | 国产黄色大片 | 欧美一二三视频 | 91成人免费 | 天天爱天天操天天爽 | 日日夜夜狠狠干 | 99久久99久久免费精品蜜臀 | 天天色天天艹 | 99亚洲国产精品 | 天天操夜夜看 | 久久久久看片 | 国产在线观看地址 | 在线观看中文字幕一区 | 在线午夜电影神马影院 | 亚洲区二区| 五月婷网站 | 久久久www成人免费精品张筱雨 | 主播av在线 | 婷婷色在线视频 | 色视频成人在线观看免 | 天天操夜夜摸 | 国产一区高清在线 | www.久久久.com | 久久国产精品久久久久 | 日韩在线视频二区 | 天天操夜夜逼 | 一区二区三区免费看 | 在线视频 精品 | 免费观看第二部31集 | 99色在线播放 | 久久亚洲专区 | 草莓视频在线观看免费观看 | 日本精品一区二区三区在线播放视频 | av直接看| 996久久国产精品线观看 | 久久精品视频一 | 天天操天天操天天 | 成人性生活大片 | 亚洲高清视频在线播放 | 一级做a视频 | 特级西西444www大精品视频免费看 | 天天爱天天操天天爽 | 免费视频久久久久久久 | 天天综合视频在线观看 | 国产成人一区二区啪在线观看 | 激情网五月天 | 欧美国产高清 | 一二区精品 | 国内精品久久久久久久久久 | av一级片 | 米奇影视7777 | 在线日韩中文字幕 | 右手影院亚洲欧美 | 国产精品美女久久久久久久久久久 | 国产一级特黄毛片在线毛片 | 激情www| 西西www4444大胆视频 | 日韩一区二区三区免费视频 | 91在线看片 | 在线小视频 | 色欧美视频 | 久久免费影院 | 黄色a大片 | 国产色小视频 | 四虎成人av | 日韩激情综合 | 午夜电影久久 | 在线观看免费黄视频 | 免费看毛片在线 | 97国产超碰在线 | 久久久麻豆精品一区二区 | 日韩av伦理片 | 中文字幕在线观看不卡 | 国产精品毛片久久久久久 | 国产免费xvideos视频入口 | av在线超碰 | 国产黄av| 中文字幕在线观看日本 | 午夜精品福利一区二区三区蜜桃 | 国产美女视频网站 | 九草在线视频 | 精品91视频| 91秒拍国产福利一区 | 国产又粗又猛又黄又爽的视频 | 免费在线观看av网址 | 一区二区在线不卡 | 久久久久 | 国内精品久久久精品电影院 | 成人黄在线 | 中文字幕国产在线 | 精品欧美一区二区三区久久久 | 亚洲精品午夜久久久 | www.一区二区三区 | 欧美色图亚洲图片 | 精品黄色片 | 国产精品成人一区二区三区吃奶 | 久久精久久精 | 在线观看精品视频 | 国产成人精品久久久 | 激情喷水 | 亚洲欧美综合 | 亚洲小视频在线 | 91亚洲成人 | 国产无区一区二区三麻豆 | 91夫妻视频 | 免费韩国av | 免费在线成人av | 岛国大片免费视频 | 天天爱天天操天天射 | 国产精品久久久电影 | 麻豆91在线观看 | 中文字幕在线观看第一页 | 亚洲日本欧美 | 日韩精品一区二区三区三炮视频 | 欧美一级xxxx | 久99久久| 男女拍拍免费视频 | 99色在线视频 | 91自拍成人 | 5月丁香婷婷综合 | 人人爽人人射 | 日日射av| a级一a一级在线观看 | 欧美孕妇与黑人孕交 | 欧美精品中文在线免费观看 | 国产精品大片在线观看 | 久久精品系列 | 久久精品中文字幕少妇 | 黄色91免费观看 | 高清一区二区三区 | 在线亚洲小视频 | 一级黄色电影网站 | 久久久av电影 | 黄色电影小说 | 免费在线观看成人小视频 | 91精品一区国产高清在线gif | 天天天天射 | 国产精品一区在线 | 在线 视频 一区二区 | 久久人91精品久久久久久不卡 | 久久首页 | 手机在线中文字幕 | av在线免费在线 | 精品一区二区视频 | 精品久久久久久久久久岛国gif | 成人免费视频视频在线观看 免费 | 色的网站在线观看 | 97碰视频| 日日夜夜狠狠操 | 日韩精品久久久久久久电影竹菊 | 免费在线观看亚洲视频 | 国产 视频 高清 免费 | 免费午夜网站 | 亚洲精品乱码久久 | 久一在线 | 4438全国亚洲精品在线观看视频 | 日韩av女优视频 | 一区二区伦理电影 | 久久av不卡 | 91传媒在线| 手机看片中文字幕 | 中文字幕av日韩 | 亚洲精品mv在线观看 | 午夜精品中文字幕 | 成人黄色中文字幕 | 日韩a级免费视频 | 一级免费看 | 日韩丝袜在线观看 | 国产精品一区二区三区免费视频 | 婷婷综合成人 | 免费三级黄色片 | 久久综合在线 | 97免费在线视频 | 狠狠狠狠狠干 | 97国产电影 | 久久成年人 | 欧美日本日韩aⅴ在线视频 插插插色综合 | 日本精品视频一区二区 | 久久伊人精品一区二区三区 | 久久99国产精品自在自在app | 男女激情片在线观看 | 日韩免费在线观看视频 | 91成人精品视频 | 国产69精品久久久久久 | 天天草天天干天天射 | 亚洲专区在线播放 | 午夜av激情 | 国产 视频 久久 | 在线观看视频免费播放 | 久久精品国产美女 | 国产黄色在线看 | 五月婷婷一区二区三区 | 国产精品精品 | 深夜男人影院 | 精品国内自产拍在线观看视频 | 亚洲日本成人网 | 四虎影视精品永久在线观看 | 成年一级片 | 成年人免费av网站 | 久色小说 | 色网站免费在线观看 | 国产精品久久久 | 久久久久久久久久伊人 | 亚洲国产精品va在线看黑人 | 久久天天躁狠狠躁夜夜不卡公司 | 色视频成人在线观看免 | 又黄又爽的免费高潮视频 | 四虎影院在线观看av | 中文字幕在线视频第一页 | 叶爱av在线 | 国产高清不卡 | 91av免费在线观看 | 欧美韩国日本在线 | 成人av在线影院 | 欧美日韩在线视频观看 | 91免费的视频在线播放 | 日女人免费视频 | 国产又粗又猛又爽又黄的视频先 | 91视频91蝌蚪| 中文字幕第一页在线播放 | 天天狠狠操 | 欧美精品久久久久久久亚洲调教 | 最近日本mv字幕免费观看 | 99热国产在线观看 | 成年人国产在线观看 | 99国内精品久久久久久久 | 黄色成人91 | 中文字幕成人网 | 91传媒视频在线观看 | 久久久久久久久久电影 | 91av播放 | 超碰在线日韩 | 国产精品视频999 | 久热免费在线观看 | 毛片无卡免费无播放器 | 日韩理论在线观看 | 亚洲视屏在线播放 | 九九综合九九 | 久久久精品视频网站 | 黄在线免费看 | 色鬼综合网 | 久久久久久久久久久精 | 五月天婷婷丁香花 | 99久久久久久国产精品 | 99久免费精品视频在线观看 | 激情五月激情综合网 | 激情久久伊人 | 天天舔夜夜操 | 激情网站免费观看 | 97国产大学生情侣酒店的特点 | 97超碰人人模人人人爽人人爱 | 国产一区二区三区高清播放 | 在线有码中文 | 成人在线视 | 精品国产一区二区三区四区vr | 黄色福利网 | 国产91粉嫩白浆在线观看 | 激情综合网色播五月 | 99c视频高清免费观看 | 蜜桃视频在线视频 | 又粗又长又大又爽又黄少妇毛片 | 一区三区视频在线观看 | 黄a在线观看 | av资源中文字幕 | 日韩电影一区二区在线 | 欧洲视频一区 | 久久视频这里有久久精品视频11 | 亚洲国产影院av久久久久 | 中文字幕在线第一页 | 亚洲aⅴ在线观看 | 亚洲免费高清视频 | 亚洲国产精品一区二区尤物区 | 中文字幕中文字幕 | 国产一区二区久久久 | 最新av电影网址 | 成人91在线 | 久要激情网| 国产亚洲成人网 | 国内成人综合 | 国偷自产中文字幕亚洲手机在线 | 在线 你懂 | 国内精品久久久久影院一蜜桃 | freejavvideo日本免费| 青青草久草在线 | 麻豆一精品传二传媒短视频 | 在线观看岛国片 | 99久久久国产精品免费99 | 中文字幕在线视频免费播放 | 国产一区二区在线视频观看 | 亚洲激情在线 | 国产精品中文字幕av | 激情伊人五月天 | 日韩精品一区二区三区免费观看视频 | 久久精品伊人 | 日日夜夜精品视频 | 国产精品18久久久久久久 | 日韩av在线一区二区 | 国产精品久久久久久久久费观看 | 狠狠做深爱婷婷综合一区 | 国产精品av久久久久久无 | 久久精品在线免费观看 | 黄色a在线| 亚洲日本激情 | 中文字幕亚洲综合久久五月天色无吗'' | 国产精品久久久久aaaa九色 | 亚洲国产中文字幕在线视频综合 | 国产福利一区在线观看 | 综合久久2023 | 中午字幕在线观看 | 91麻豆精品一区二区三区 | 在线看国产日韩 | 免费午夜在线视频 | 九精品 | 天天射天天做 | 日本不卡久久 | 精品一区二区在线免费观看 | 五月激情天 | 亚洲狠狠干 | 久久综合国产伦精品免费 | 久久久久女教师免费一区 | 久久精品爱爱视频 | 国产在线精品一区二区不卡了 | 国产精品视频区 | 国产午夜精品视频 | 中文字幕在线播出 | 久久麻豆精品 | 日韩中文字幕免费电影 | 天天操天天摸天天干 | 久久久免费视频播放 | 国产欧美精品一区aⅴ影院 99视频国产精品免费观看 | 免费看一级特黄a大片 | 中文字幕成人网 | 午夜丰满寂寞少妇精品 | 精品久久久久久亚洲综合网 | 国产特级毛片aaaaaa | 亚洲播放一区 | 色91在线视频 | 黄色大片日本 | 黄色免费网站下载 | 亚洲精品毛片一级91精品 | 日韩在线播放av | 国产免费a | 欧美性生活一级片 | 天天干天天做天天操 | 免费观看一区 | 九色福利视频 | 成年人在线观看网站 | 国产精品18久久久久白浆 | 国产精品久久久一区二区 | 日本女人的性生活视频 | 日韩精品中文字幕久久臀 | 中文字幕在线观看完整版电影 | 日韩在线不卡视频 | 久久久久久视频 | 中文字幕 国产专区 | 久久久久欧美精品 | 麻豆 91 在线| 91网在线 | 亚洲午夜精品久久久 | 国产精品自产拍 | 九九久久成人 | 黄色免费视频在线观看 | 成人免费视频网站 | 超碰成人免费电影 | 精品国产自在精品国产精野外直播 | 日韩网站在线免费观看 | 国产在线精品一区二区三区 | 欧美天天干 | 国产 欧美 日本 | 在线亚洲欧美视频 | 欧美日一级片 | va视频在线 | 黄色精品免费 | 成片视频在线观看 | 亚洲天堂网视频 | 91高清视频| 中文字幕在线视频网站 | 又粗又长又大又爽又黄少妇毛片 | 国产精品自产拍在线观看中文 | 91av观看 | 在线免费日韩 | 久久精品一区二区三区国产主播 | 色婷婷婷 | 日韩最新在线 | 国产精品国产毛片 | 999视频在线播放 | 最新国产中文字幕 | 欧美激情xxxx | 亚州日韩中文字幕 | 国内精品久久久久影院男同志 | 怡红院av | 久草免费新视频 | 蜜臀久久99精品久久久酒店新书 | 欧美日韩不卡一区二区三区 | www.色午夜,com | 日韩v欧美v日本v亚洲v国产v | 中文字幕中文字幕 | 日韩欧美综合视频 | 韩日精品在线 | 亚洲成人黄色av | 国产视频资源 | 欧美国产亚洲精品久久久8v | 日韩精品首页 | 97在线观看视频国产 | 亚洲国产精久久久久久久 | 伊人久久五月天 | 综合网天天色 | 精品视频久久久久久 | 中文字幕中文字幕在线中文字幕三区 | 日本女人逼| 欧美午夜性| 成人a在线观看 | 国产在线观看a | 在线视频专区 | 久久久亚洲网站 | 99视频偷窥在线精品国自产拍 | 国产精品久久婷婷六月丁香 | 黄色av一区 | 成人福利在线播放 | 天天爽人人爽夜夜爽 | 日b视频国产 | 一区二区精品国产 | 最近中文字幕高清字幕免费mv | 久久视频精品在线观看 | 日本黄色免费观看 | 中文字幕精品一区二区三区电影 | 国产日韩av在线 | 亚洲黄色激情小说 | 日精品在线观看 | 免费能看的av | 国产视频在线观看免费 | 精品国产三级 | 一区二区中文字幕在线观看 | 免费美女久久99 | 婷婷久久综合网 | 天天综合网天天 | 久久av中文字幕片 | 97精品国产97久久久久久免费 | 蜜臀av性久久久久蜜臀aⅴ四虎 | 国产亚洲久久 | 国产高清av | 亚洲精品高清视频在线观看 | 色 免费观看 | 国产xxxxx在线观看 | 欧美片一区二区三区 | 久久免费视频7 | 97精品国产97久久久久久春色 | 六月天综合网 | 欧美亚洲精品在线观看 | 国产成人精品久久亚洲高清不卡 | 国产麻豆视频在线观看 | 制服丝袜一区二区 | 国产999精品久久久久久绿帽 | 午夜骚影 | 久久这里只有精品1 | 欧美性久久久久久 | 91精品系列| 亚洲a网 | www.久草.com | 亚洲精品资源 | 国产一卡二卡四卡国 | 在线激情av电影 | 精品国产乱码久久久久久天美 | 一本一本久久aa综合精品 | 国产精品美女久久久久久久久久久 | 日韩 在线a| 中文字幕在线播放一区 | 日韩黄在线观看 | 日韩视频a | 成人精品国产 | 97福利在线观看 | 久久精品久久久久久久 | 欧美极品少妇xbxb性爽爽视频 | 99热这里只有精品久久 | 久久99精品国产一区二区三区 | 九色在线 | 免费一级日韩欧美性大片 | 99热在线观看免费 | 成人教育av | 亚洲年轻女教师毛茸茸 | 在线欧美国产 | www.五月天激情 | 日韩成人精品一区二区三区 | 成人久久18免费网站 | 97超碰.com| 亚洲免费小视频 | 久久久久久毛片 | 日韩精品91偷拍在线观看 | 日日干综合 | 九九九热精品 | 欧美激情视频在线免费观看 | 91九色蝌蚪 | 日本xxxx裸体xxxx17 | 西西444www| 国产淫片免费看 | 欧美色道| 日本久久久久久久久久 | 成人蜜桃网 | 97视频总站 | 久久精品人人做人人综合老师 | 成人av资源网站 | 久久av中文字幕片 | 国产精品视频在线看 | 九九热在线播放 | 日批视频在线播放 | www免费看 | av综合在线观看 | 久视频在线播放 | 在线观看的av| 欧美电影在线观看 | 免费观看国产成人 | 久久久久99精品国产片 | 国产日韩欧美自拍 | 亚洲天堂网视频在线观看 | 久久99精品久久只有精品 | 菠萝菠萝在线精品视频 | 激情五月婷婷激情 | 日韩在线观看视频网站 | 精品在线观看一区二区 | 五月天久久综合 | 一本一道久久a久久综合蜜桃 | 一级黄色大片在线观看 | 国产精品不卡av | 亚洲人人射 | 免费在线观看成人 | 日批视频 | 在线免费观看的av网站 | 国产精品99久久久精品 | 国产综合视频在线观看 | 91资源在线视频 | 狠狠撸电影 | 91精品国产高清自在线观看 | 黄色日批网站 | 色多多污污在线观看 | 99国产精品视频免费观看一公开 | 中文字幕日韩av | 你操综合 | 国产美女久久久 | 成人午夜性影院 | 日韩1级片 | 成人av在线影视 | 日本韩国在线不卡 | 91九色精品 | av久久在线| 综合影视 | www.亚洲黄| 人人爽人人爽人人片 | 精品99免费视频 | 日本最新高清不卡中文字幕 | 日日爱视频 | 成人毛片在线观看视频 | 欧美亚洲另类在线视频 | 97成人超碰 | 久久免费视频一区 | 亚洲精品在线电影 | 成人av教育 | 天天激情综合网 | 久久黄色网页 | 丝袜美女在线 | 天天综合日日夜夜 | 欧美精品国产综合久久 | 久久免费av电影 | 91色影院 | 欧美国产日韩在线观看 | 日韩网站免费观看 | 91丨九色丨91啦蝌蚪老版 | 中文字幕在线视频一区二区 | 国产又粗又猛又黄又爽的视频 | 欧美一级小视频 | 久久9精品| 国产精品第一 | 国产视频首页 | 一区二区三区日韩在线观看 | 一本一本久久a久久精品综合妖精 | 日韩xxx视频 | 色视频在线 | 中文欧美字幕免费 | 一区二区不卡在线观看 | av成人免费在线观看 | 日韩在线一区二区免费 | 中文字幕在线观看第二页 | 久久综合久久综合久久 | 国产一级在线观看视频 | 天天操天天爽天天干 | 亚洲涩涩色 | 国产欧美在线一区 | 亚洲最快最全在线视频 | 久久免费视频2 | 中文字幕精品一区 | 色综合天天色综合 | 日韩一区二区免费在线观看 | 探花在线观看 | 久久久综合精品 | 在线免费观看欧美日韩 | 啪啪免费试看 | 成人国产综合 | 九色视频网 | 全黄网站 | 欧美日韩视频在线一区 | 久久影视一区 | 黄色片免费电影 | 91九色视频国产 | 国产免费资源 | 日韩r级在线 | 人人爱人人射 | 91在线观看欧美日韩 | 亚洲一区 影院 | 免费看特级毛片 | 91丨九色丨蝌蚪丨老版 | 四虎在线永久免费观看 | 日韩综合在线观看 | 天天操天天操 | 欧美a级在线 | 国产一区在线不卡 | 高清视频一区 | 6699私人影院 | 亚洲精品成人av在线 | 欧美精品久久久久久久免费 | 69视频网站 | 久久国产欧美日韩精品 | 婷婷激情av| 在线播放av网址 | 亚洲最大成人网4388xx | 日本久久免费视频 | 国产亚洲精品久久久久久无几年桃 | 在线成人欧美 | 天天干夜夜想 | 国产黄在线播放 | 亚洲激情久久 | 亚洲在线观看av | 成人av电影在线观看 | 天天色天天射综合网 | 国产综合在线观看视频 | 亚洲v欧美v国产v在线观看 | 91丨九色丨国产丨porny精品 | 婷婷丁香久久五月婷婷 | 激情九九 | 亚洲激情国产精品 | 国产99久久九九精品免费 | 精品一区二区电影 | 亚洲最新av网站 | 一区二区 精品 | 中国一级片免费看 | 亚洲精品一区二区三区高潮 | 狠狠干成人综合网 | 欧美精品一区二区免费 | 国产精品一级在线 | 蜜臀av夜夜澡人人爽人人桃色 | 日韩一区二区三免费高清在线观看 | 四虎在线免费观看 | 激情九九| 日本一区二区免费在线观看 | 天天爱天天射 | 中文字幕欲求不满 | 综合色久 | 久久久精品免费看 | 在线观看a视频 | 国产精品网站一区二区三区 | 久久免费视频这里只有精品 | 天天要夜夜操 | 99亚洲国产精品 | 黄色小说免费在线观看 | 天天操综合 | 国产午夜在线观看视频 | 免费观看第二部31集 | 激情自拍av| 久久国产精品久久精品国产演员表 | 亚洲va在线va天堂 | 四虎影视成人精品国库在线观看 | 在线观看一区视频 | 天天操狠狠操夜夜操 | 在线观看视频精品 | 日韩高清免费无专码区 | 婷婷av网 | 欧美日在线观看 | 免费看日韩| 91久久偷偷做嫩草影院 | 插综合网 | 日日操日日插 | 狠狠色香婷婷久久亚洲精品 | 国产精品高清免费在线观看 | 国产精品久久久久久久久久三级 | 国产精品久久久久久久7电影 | 天天操综| 中文字幕在线免费播放 | 国产精品专区在线 | 国产亚洲欧美精品久久久久久 | 91精品一区二区三区蜜臀 | 国产精品男女视频 | 免费进去里的视频 | 免费av网站在线 | 中文字幕免费观看视频 | 久久小视频 | 久久av免费| 亚洲国产精品久久久久久 | 久久国产精品久久久久 | 探花视频在线观看免费 | 国产成人精品免高潮在线观看 | 久久精品视频在线免费观看 | 黄色av一区| 视频成人永久免费视频 | 日本黄色免费播放 | 久久手机免费视频 | 中文字幕免费观看 | 福利av影院 | 亚洲精品大片www | 日韩一区二区三区免费电影 | 欧美日韩免费在线视频 | 国产精品麻豆一区二区三区 | 色在线网 | 国产美女精品视频 | 国产九九精品 | 973理论片235影院9 | 热久久精品在线 | 亚洲人xxx | 超碰在线公开免费 | 国产精品去看片 | 欧美一区二区伦理片 | 狠狠色丁香婷婷综合基地 | 在线免费观看视频你懂的 | 久久公开免费视频 | 久色小说 | 日本公妇在线观看高清 | 国产丝袜制服在线 | 日韩精品中文字幕在线观看 | 亚洲成成品网站 | 最新日韩在线观看视频 | 一区二区三区四区在线免费观看 | 成人永久视频 | 探花视频在线观看+在线播放 | 九九视频精品在线 | 亚洲 欧美 91 | 国产一区二区三区免费在线 | 99精品视频在线播放免费 | 色香蕉网 | 五月天亚洲激情 | 久久综合久久综合这里只有精品 | 视频在线一区二区三区 | 国产一区二区久久久久 | 亚洲女裸体| 成人黄色在线 | 日韩高清dvd| 色综合色综合久久综合频道88 | 美女网站色免费 | 在线观看日韩中文字幕 | 国产精品99视频 | 精品国产福利在线 | 97国产超碰| 久久99久久久久久 | 成人一级在线 | 成人免费在线观看入口 | 国产精品一区二区免费看 | 一级黄色片在线观看 | 久久国产精品系列 | av蜜桃在线 | 国产黄色精品视频 | 国产精品毛片久久久久久 | 黄网站app在线观看免费视频 | 成人免费在线视频观看 | 91片网 | 亚洲a资源 | 97天堂| 欧美日韩a视频 | 欧美日韩另类在线观看 | 色天天中文 | 免费91麻豆精品国产自产在线观看 | 激情综合色图 | 99r在线视频| 国产 字幕 制服 中文 在线 | 亚洲精品自在在线观看 | 国产精品va最新国产精品视频 | 色老板在线视频 | 国产亚洲精品久久19p | 国产精品欧美久久久久三级 | 久久免费观看视频 | 日韩精品一区二区免费视频 | 国产麻豆剧传媒免费观看 | 欧美少妇xxxxxx | 99视频在线播放 | 久久久久 免费视频 | 天天干天天弄 | 久久久电影网站 | 啪啪资源| 激情五月综合 | 三级视频日韩 | 国产精品久久久久一区二区 | 日本在线观看一区二区三区 | 高清国产在线一区 | 国产免费看| 高清av中文在线字幕观看1 | 精品欧美日韩 | 4438全国亚洲精品观看视频 | 韩日色视频 | 国产视频中文字幕在线观看 | 国产精品成人一区二区三区 | 一区二区三区免费播放 | 欧美综合久久久 | 免费看黄的 | 涩涩成人在线 | 最近中文字幕在线中文高清版 | 国产字幕在线播放 | 久久久久国产a免费观看rela | 成人av电影在线 | 国产91av视频在线观看 | 91亚洲精品乱码久久久久久蜜桃 | 欧美地下肉体性派对 | 亚洲精品中文在线资源 | 99九九视频| 色婷婷av在线 | 欧美另类成人 | 91精品国产成人www | 正在播放国产一区二区 | 亚洲国产伊人 | 精品a视频 | 最近中文国产在线视频 | 天天干天天操天天 | 免费观看成人网 | 玖玖玖影院 | 国产色爽 | 日韩美女免费线视频 | 一区二区网 | 亚洲综合欧美日韩狠狠色 | 久久免费视频一区 | 国内成人精品视频 | 欧美伦理电影一区二区 | 国产在线精品播放 | 国产一区二区三精品久久久无广告 | 色综合久久88色综合天天 | 国产精品专区在线 | 欧美日韩精品在线免费观看 | 91视频免费网址 | 99视频精品视频高清免费 | 精品免费一区 | 91九色成人| 又大又硬又黄又爽视频在线观看 | 99精品视频在线观看视频 | 夜夜操天天干 | 日色在线视频 | 超碰国产人人 | 免费成人在线电影 | 亚洲精品永久免费视频 | 视频一区二区在线 | 天天综合日日夜夜 | 久久免费视频在线观看6 | 中文字幕在线有码 | 在线 国产一区 | 91系列在线观看 | 亚洲a资源 | 成人午夜剧场在线观看 | 国产一区二区电影在线观看 | 亚洲情感电影大片 | 日韩欧美一级二级 | 久久久久99精品国产片 | 99免费在线播放99久久免费 | 免费精品在线 | 欧美久久久久久久久久久久久 | 国产精品免费高清 | 免费成人在线观看 | 热久久免费国产视频 | 日韩在线一区二区免费 | 日本韩国精品一区二区在线观看 | 激情欧美一区二区三区 | 欧美色图东方 | 99精品视频精品精品视频 | 国产又粗又猛又色 | 亚洲国内精品 | 久爱精品在线 | 91精品免费在线视频 | 中国精品少妇 | 亚洲婷婷免费 | 日韩91精品 | 中文字幕一区二区三区在线视频 | 久久综合中文字幕 | 久久爱资源网 | 久热久草在线 | 国产首页 | 日韩精品久久久久 | 亚洲精品国产麻豆 | 国产精品国产亚洲精品看不卡 | 久久99国产一区二区三区 | 99精品久久只有精品 | 国产精品久久久久永久免费观看 | 国产九色视频在线观看 | 国产精品1区2区 | 五月天色综合 | 中文字幕在线视频第一页 | 国产精品一区二区免费在线观看 | 日本中文字幕在线免费观看 | 69欧美视频 | 波多野结衣在线播放视频 | 欧美一区二区在线刺激视频 | h视频日本 | 天天av天天| 色成人亚洲 | 久久在线免费视频 | 91av在线免费视频 | 免费观看国产成人 | 精品国产一区二区三区蜜臀 | 久久艹艹 | 天天做天天爱夜夜爽 |