Java — Multithreading,Parallel & Asynchronous Coding in Modern Java
We’ll see how to make the use of Thread, Runnable and Executor service interface to achieve Parallel and Aync programming
public class ProductInfoService {
public ProductInfo retrieveProductInfo(String productId) {
delay(1000);
return ProductInfo.builder()
.productId(productId)
.productOption(ProductOption.builder().productionOptionId(1).size("64GB").color("Black").price(699.99).build())
.productOption(new ProductOption(2, "128GB", "Black", 749.99))
.productOption(new ProductOption(3, "128GB", "Black1", 749.99))
.productOption(new ProductOption(4, "128GB", "Black2", 749.99))
.build();
}
}
ReviewService.java
public class ReviewService {
public Review retrieveReviews(String productId) {
delay(1000);
return Review.builder()
.noOfReviews(200)
.overallRating(4.5)
.build();
}
}
CommonUtil.java
public class CommonUtil {
public static StopWatch stopWatch = StopWatch.create();
public static void delay(long delayMilliSeconds) {
try {
sleep(delayMilliSeconds);
} catch (Exception e) {
LoggerUtil.log("Exception is :" + e.getMessage());
}
}
public static String transForm(String s) {
CommonUtil.delay(500);
return s.toUpperCase();
}
public static void startTimer() {
stopWatch.start();
}
public static void timeTaken() {
stopWatch.stop();
log("Total Time Taken : " + stopWatch.getTime());
}
public static void stopWatchReset() {
stopWatch.reset();
}
public static int noOfCores() {
return Runtime.getRuntime().availableProcessors();
}
}
Using Runnable Interface —
ProductServiceUsingThread.java
public class ProductServiceUsingThreads {
private ProductInfoService productInfoService;
private ReviewService reviewService;
public ProductServiceUsingThreads(ProductInfoService productInfoService, ReviewService reviewService) {
this.productInfoService = productInfoService;
this.reviewService = reviewService;
}
public Product retrieveProductDetails(String productId) throws InterruptedException {
CommonUtil.stopWatch.start();
ProductInfoServiceRunnable productInfoServiceRunnable = new ProductInfoServiceRunnable(productId);
ReviewServiceRunnable reviewServiceRunnable = new ReviewServiceRunnable(productId);
Thread productInfoServiceThread = new Thread(productInfoServiceRunnable);
Thread reviewServiceThread = new Thread(reviewServiceRunnable);
productInfoServiceThread.start();
reviewServiceThread.start();
productInfoServiceThread.join();
reviewServiceThread.join();
ProductInfo productInfo = productInfoServiceRunnable.getProductInfo();
Review review = reviewServiceRunnable.getReview();
CommonUtil.stopWatch.stop();
LoggerUtil.log("Total Time Taken : "+ CommonUtil.stopWatch.getTime());
return new Product(productId, productInfo, review);
}
public static void main(String[] args) throws InterruptedException {
ProductInfoService productInfoService = new ProductInfoService();
ReviewService reviewService = new ReviewService();
ProductServiceUsingThreads productService = new ProductServiceUsingThreads(productInfoService, reviewService);
String productId = "ABC123";
Product product = productService.retrieveProductDetails(productId);
LoggerUtil.log("Product is " + product);
}
/**
* ProductInfo
*/
private class ProductInfoServiceRunnable implements Runnable{
private String productId;
private ProductInfo productInfo;
public ProductInfoServiceRunnable(String productId) {
this.productId = productId;
}
@Override
public void run() {
// blocking call
productInfo = productInfoService.retrieveProductInfo(productId);
}
public ProductInfo getProductInfo() {
return productInfo;
}
}
/**
* Review
*/
private class ReviewServiceRunnable implements Runnable{
private String productId;
@Getter
private Review review;
public ReviewServiceRunnable(String productId) {
this.productId = productId;
}
@Override
public void run() {
// blocking call
review = reviewService.retrieveReviews(productId);
}
}
}
Using ExecutorService Interface —
public class ProductServiceUsingExecutor {
private static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
private ProductInfoService productInfoService;
private ReviewService reviewService;
public ProductServiceUsingExecutor(ProductInfoService productInfoService, ReviewService reviewService) {
this.productInfoService = productInfoService;
this.reviewService = reviewService;
}
public Product retrieveProductDetails(String productId) throws ExecutionException, InterruptedException {
CommonUtil.stopWatch.start();
Future<ProductInfo> productInfoFuture = executorService.submit(() -> productInfoService.retrieveProductInfo(productId));
Future<Review> reviewFuture = executorService.submit(() -> reviewService.retrieveReviews(productId));
ProductInfo productInfo = productInfoFuture.get(); // blocking call
Review review = reviewFuture.get(); // blocking call
CommonUtil.stopWatch.stop();
LoggerUtil.log("Total Time Taken : " + CommonUtil.stopWatch.getTime());
return new Product(productId, productInfo, review);
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ProductInfoService productInfoService = new ProductInfoService();
ReviewService reviewService = new ReviewService();
ProductServiceUsingExecutor productService = new ProductServiceUsingExecutor(productInfoService, reviewService);
String productId = "ABC123";
Product product = productService.retrieveProductDetails(productId);
LoggerUtil.log("Product is " + product);
executorService.shutdown();
}
}