Skip to content

Commit 9c8d5c1

Browse files
committed
CompletableFuture examples
1 parent 150e8bd commit 9c8d5c1

File tree

9 files changed

+331
-0
lines changed

9 files changed

+331
-0
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package lambdasinaction.chap10;
2+
3+
import java.text.*;
4+
import java.util.*;
5+
import java.util.concurrent.*;
6+
7+
import static lambdasinaction.chap10.Util.*;
8+
9+
public class AsyncShop {
10+
11+
private final String name;
12+
private final Random random;
13+
14+
public AsyncShop(String name) {
15+
this.name = name;
16+
random = new Random(name.charAt(0) * name.charAt(1) * name.charAt(2));
17+
}
18+
19+
public Future<Double> getPrice(String product) {
20+
/*
21+
CompletableFuture<Double> futurePrice = new CompletableFuture<>();
22+
new Thread( () -> {
23+
try {
24+
double price = calculatePrice(product);
25+
futurePrice.complete(price);
26+
} catch (Exception ex) {
27+
futurePrice.completeExceptionally(ex);
28+
}
29+
}).start();
30+
return futurePrice;
31+
*/
32+
return CompletableFuture.supplyAsync(() -> calculatePrice(product));
33+
}
34+
35+
private double calculatePrice(String product) {
36+
delay();
37+
if (true) throw new RuntimeException("product not available");
38+
return format(random.nextDouble() * product.charAt(0) + product.charAt(1));
39+
}
40+
41+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package lambdasinaction.chap10;
2+
3+
import java.util.concurrent.*;
4+
5+
public class AsyncShopClient {
6+
7+
public static void main(String[] args) {
8+
AsyncShop shop = new AsyncShop("BestShop");
9+
long start = System.nanoTime();
10+
Future<Double> futurePrice = shop.getPrice("myPhone");
11+
long incocationTime = ((System.nanoTime() - start) / 1_000_000);
12+
System.out.println("Invocation returned after " + incocationTime + " msecs");
13+
try {
14+
System.out.println("Price is " + futurePrice.get());
15+
} catch (Exception e) {
16+
throw new RuntimeException(e);
17+
}
18+
long retrivalTime = ((System.nanoTime() - start) / 1_000_000);
19+
System.out.println("Price returned after " + retrivalTime + " msecs");
20+
}
21+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package lambdasinaction.chap10;
2+
3+
import java.util.*;
4+
import java.util.concurrent.*;
5+
import java.util.stream.*;
6+
7+
public class BestPriceFinder {
8+
9+
private final List<Shop> shops = Arrays.asList(new Shop("BestPrice"),
10+
new Shop("LetsSaveBig"),
11+
new Shop("MyFavoriteShop"),
12+
new Shop("BuyItAll"),
13+
new Shop("ShopEasy"));
14+
15+
private final Executor executor = Executors.newFixedThreadPool(shops.size(), new ThreadFactory() {
16+
@Override
17+
public Thread newThread(Runnable r) {
18+
Thread t = new Thread(r);
19+
t.setDaemon(true);
20+
return t;
21+
}
22+
});
23+
24+
/*
25+
public List<String> findPriceSequential(String product) {
26+
return shops.stream()
27+
.map(shop -> shop.getName() + " price is " + shop.calculatePrice(product))
28+
.collect(Collectors.<String>toList());
29+
}
30+
31+
public List<String> findPriceParallel(String product) {
32+
return shops.parallelStream()
33+
.map(shop -> shop.getName() + " price is " + shop.calculatePrice(product))
34+
.collect(Collectors.<String>toList());
35+
}
36+
37+
public List<String> findPrice(String product) {
38+
List<CompletableFuture<String>> priceFutures =
39+
shops.stream()
40+
.map(shop -> CompletableFuture.supplyAsync(() -> shop.getName() + " price is " + shop.calculatePrice(product)))
41+
.collect(Collectors.<CompletableFuture<String>>toList());
42+
43+
List<String> prices = priceFutures.stream()
44+
.map(CompletableFuture::join)
45+
.collect(Collectors.<String>toList());
46+
return prices;
47+
//return sequence(priceFutures).join();
48+
}
49+
/*/
50+
public List<String> findPriceSequential(String product) {
51+
return shops.stream()
52+
.map(shop -> shop.getPrice(product))
53+
.map(Quote::parse)
54+
.map(Discount::applyDiscount)
55+
.collect(Collectors.<String>toList());
56+
}
57+
58+
public List<String> findPriceParallel(String product) {
59+
return shops.parallelStream()
60+
.map(shop -> shop.getPrice(product))
61+
.map(Quote::parse)
62+
.map(Discount::applyDiscount)
63+
.collect(Collectors.<String>toList());
64+
}
65+
66+
public List<String> findPrice(String product) {
67+
List<CompletableFuture<String>> priceFutures = findPriceStream(product)
68+
.collect(Collectors.<CompletableFuture<String>>toList());
69+
70+
return priceFutures.stream()
71+
.map(CompletableFuture::join)
72+
.collect(Collectors.<String>toList());
73+
}
74+
75+
public Stream<CompletableFuture<String>> findPriceStream(String product) {
76+
return shops.stream()
77+
.map(shop -> CompletableFuture.supplyAsync(() -> shop.getPrice(product), executor))
78+
.map(future -> future.thenApply(Quote::parse))
79+
.map(future -> future.thenCompose(quote -> CompletableFuture.supplyAsync(() -> Discount.applyDiscount(quote), executor)));
80+
}
81+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package lambdasinaction.chap10;
2+
3+
import java.util.*;
4+
import java.util.concurrent.*;
5+
import java.util.function.*;
6+
7+
import static java.util.stream.Collectors.toList;
8+
9+
public class BestPriceFinderMain {
10+
11+
private static BestPriceFinder bestPriceFinder = new BestPriceFinder();
12+
13+
public static void main(String[] args) {
14+
//execute("sequential", () -> bestPriceFinder.findPriceSequential("myPhone"));
15+
//execute("parallel", () -> bestPriceFinder.findPriceParallel("myPhone"));
16+
//execute("composed CompletableFuture", () -> bestPriceFinder.findPrice("myPhone"));
17+
printPricesStream();
18+
}
19+
20+
private static void printPricesStream() {
21+
long start = System.nanoTime();
22+
List<CompletableFuture<Void>> futures =
23+
bestPriceFinder.findPriceStream("myPhone")
24+
.map(f -> f.thenAccept(s -> System.out.println(s + " (find in " + ((System.nanoTime() - start) / 1_000_000) + " msecs)")))
25+
.collect(toList());
26+
27+
CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join();
28+
}
29+
30+
private static void execute(String msg, Supplier<List<String>> s) {
31+
long start = System.nanoTime();
32+
System.out.println(s.get());
33+
long duration = (System.nanoTime() - start) / 1_000_000;
34+
System.out.println(msg + " done in " + duration + " msecs");
35+
}
36+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package lambdasinaction.chap10;
2+
3+
import java.util.*;
4+
5+
import static lambdasinaction.chap10.Util.*;
6+
7+
public class Discount {
8+
9+
public enum Code {
10+
NONE(0), SILVER(5), GOLD(10), PLATINUM(15), DIAMOND(20);
11+
12+
private final int percentage;
13+
14+
Code(int percentage) {
15+
this.percentage = percentage;
16+
}
17+
}
18+
19+
public static String applyDiscount(Quote quote) {
20+
return quote.getShopName() + " price is " + Discount.apply(quote.getPrice(), quote.getDiscountCode());
21+
}
22+
private static double apply(double price, Code code) {
23+
delay();
24+
return format(price * (100 - code.percentage) / 100);
25+
}
26+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package lambdasinaction.chap10;
2+
3+
public class Quote {
4+
5+
private final String shopName;
6+
private final double price;
7+
private final Discount.Code discountCode;
8+
9+
public Quote(String shopName, double price, Discount.Code discountCode) {
10+
this.shopName = shopName;
11+
this.price = price;
12+
this.discountCode = discountCode;
13+
}
14+
15+
public static Quote parse(String s) {
16+
String[] split = s.split(":");
17+
String shopName = split[0];
18+
double price = Double.parseDouble(split[1]);
19+
Discount.Code discountCode = Discount.Code.valueOf(split[2]);
20+
return new Quote(shopName, price, discountCode);
21+
}
22+
23+
public String getShopName() {
24+
return shopName;
25+
}
26+
27+
public double getPrice() {
28+
return price;
29+
}
30+
31+
public Discount.Code getDiscountCode() {
32+
return discountCode;
33+
}
34+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package lambdasinaction.chap10;
2+
3+
import java.util.*;
4+
5+
import static lambdasinaction.chap10.Util.*;
6+
7+
public class Shop {
8+
9+
private final String name;
10+
private final Random random;
11+
12+
public Shop(String name) {
13+
this.name = name;
14+
random = new Random(name.charAt(0) * name.charAt(1) * name.charAt(2));
15+
}
16+
17+
public String getPrice(String product) {
18+
double price = calculatePrice(product);
19+
Discount.Code code = Discount.Code.values()[random.nextInt(Discount.Code.values().length)];
20+
return name + ":" + price + ":" + code;
21+
}
22+
23+
public double calculatePrice(String product) {
24+
delay();
25+
return format(random.nextDouble() * product.charAt(0) + product.charAt(1));
26+
}
27+
28+
public String getName() {
29+
return name;
30+
}
31+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package lambdasinaction.chap10;
2+
3+
import java.text.*;
4+
import java.util.*;
5+
import java.util.concurrent.*;
6+
import java.util.stream.*;
7+
8+
public class Util {
9+
10+
private static final Random RANDOM = new Random(0);
11+
private static final DecimalFormat formatter = new DecimalFormat("#.##", new DecimalFormatSymbols(Locale.US));
12+
13+
public static void delay() {
14+
//int delay = 1000;
15+
int delay = 500 + RANDOM.nextInt(2000);
16+
try {
17+
Thread.sleep(delay);
18+
} catch (InterruptedException e) {
19+
throw new RuntimeException(e);
20+
}
21+
}
22+
23+
public static double format(double number) {
24+
synchronized (formatter) {
25+
return new Double(formatter.format(number));
26+
}
27+
}
28+
29+
public static <T> CompletableFuture<List<T>> sequence(List<CompletableFuture<T>> futures) {
30+
/*
31+
CompletableFuture<Void> allDoneFuture =
32+
CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
33+
return allDoneFuture.thenApply(v ->
34+
futures.stream().
35+
map(future -> future.join()).
36+
collect(Collectors.<T>toList())
37+
);
38+
*/
39+
return CompletableFuture.supplyAsync(() -> futures.stream().
40+
map(future -> future.join()).
41+
collect(Collectors.<T>toList()));
42+
}
43+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package lambdasinaction.chap9;
2+
3+
import java.util.*;
4+
5+
import static java.util.Optional.of;
6+
import static java.util.Optional.empty;
7+
8+
public class OperationsWithOptional {
9+
10+
public static void main(String... args) {
11+
System.out.println(max(of(3), of(5)));
12+
System.out.println(max(empty(), of(5)));
13+
}
14+
15+
public static final Optional<Integer> max(Optional<Integer> i, Optional<Integer> j) {
16+
return i.flatMap(a -> j.map(b -> Math.max(a, b)));
17+
}
18+
}

0 commit comments

Comments
 (0)