Java — Multithreading,Parallel & Asynchronous Coding in Modern Java

Prateek
2 min readSep 3, 2021

--

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();
}
}

--

--

Prateek
Prateek

Written by Prateek

Java Developer and enthusiast

No responses yet