Serialization of lambda expressions – using Java 8 Lambdas in Hazelcast distributed Executor and Executor Services

Lambdas in Java 8 are a very powerful solution to ease the writing of code in many situations. One of the domains for lambdas is the programming of Callable or Runnable tasks in parallel thread execution environments.

Since Callables and Runnables themselves are functional interfaces, lambdas can easily be used for task execution within the Java executor framework. Have a look at this:

ExecutorService executorService=Executors.newFixedThreadPool(5);
executorService.submit( () -> {      
    System.out.println("the method is running on thread:"
        + Thread.currentThread().getName());
} );

When writing this we came up with the idea to also use this for Hazelcast distributed executor service which in fact is nothing else than an ExecutorService allowing us to process our function in a scalable big cluster of up to hundreds of nodes.

But simply exchanging the service with the distribution capable implementation of Hazelcast leads us to a runtime problem:

HazelcastInstance instance = Hazelcast.newHazelcastInstance(new Config());
ExecutorService executorService=instance.getExecutorService("massExecutionWithLambdas");

executorService.submit( () -> {      
    System.out.println("Running function");
});

throws an exception during runtime when trying to serialize the lambda expression to transfer the function to all cluster nodes.

com.hazelcast.nio.serialization.HazelcastSerializationException: There is no suitable serializer for class .....$$Lambda$2/.....

Woow, ok … lambdas seem not to be serializable by default. But how to make them implement the java.io.Serializable interface?

The solution is easy. We simply have to cast our lambda to java.io.Serializable. But the submit method requires a Runnable or Callable as parameter, not a Serializable. So, we have to cast the lambda to two interfaces at the same time – Runnable and Serializable. Wooo…casting to two types at the same time…this sounds strange. Ok, I agree, but it is possible in Java 8.

With the & operator in casts we can specify more than one type.

(Runnable & Serializable)

So our code looks like below

HazelcastInstance instance = Hazelcast.newHazelcastInstance(new Config());
ExecutorService executorService=instance.getExecutorService("massExecutionWithLambdas");

executorService.submit( (Runnable & Serializable)  () -> {       
    System.out.println("Running function");
} );

Very easy and very powerful, isn’t it?

Unfortunately, HazelcastInstanceAware won’t work in this scenario because the target type (Runnable & Serializable & HazelcastInstanceAware) is no longer a functional interface.

Short URL for this post: http://wp.me/p4nxik-2pm
This entry was posted in Java Basics, Java Runtimes - VM, Appserver & Cloud and tagged , , , , , . Bookmark the permalink.

Leave a Reply