Explain Codes LogoExplain Codes Logo

Functional interface that takes nothing and returns nothing

java
functional-programming
lambda-expressions
multithreading
Anton ShumikhinbyAnton Shumikhin·Feb 7, 2025
TLDR

For operations that require no input and generate no output, the Runnable interface is your go-to tool:

Runnable myAwesomeParty = () -> {}; // Behold, the world's shortest party! myAwesomeParty.run(); // Let the (non-existent) fun begin!

Here we have a lambda expression embodying the spirit of a party that promises everything but delivers nothing —a practical application when needing a functional placeholder for deferred actions.

Runnable vs the world

Java’s Runnable is best known as the kick starter for threads and executor tasks, yet, it wields a broader impact as a functional interface with no arguments and a void return, making it the ideal gizmo for your tasks that go in with nothing and come out with...well, nothing:

ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(() -> { // Joanna Public has left the building. Task code has entered. });

It's the quiet hero in scenarios like event listeners, callbacks, and actions that chant, “We don’t need no feedback!”.

In the Java landscape, like a road sign at a junction, each functional interface serves a purpose to point you in the right direction:

  • Supplier<T>: The factory from where values pop-out
  • Consumer<T>: The monster that eats up a value and asks for no cookie
  • Function<T, R>: The magician that transforms one value into another

These traffic signs of functional programming help ensure the right path for code readability and maintenance.

Dressing up Runnable

While Runnable might be the right tuxedo for a masquerade, there's room to tango with custom @FunctionalInterface when your code feels a runway might just be the fit:

@FunctionalInterface public interface Task { void perform(); } // Whoever said 'task' doesn't scream fashion! Task runwayWalk = () -> strutYourStuff();

Custom attire enhances readability and expressiveness, letting other developers not just walk, but strut down the runway of your task's intentions.

Following in Runnable's footsteps

Runnable abides by certain principles, and so should you if thread-safety, predictability, and maintenance of lambda expressions matter:

  1. Do not meddle in others' affairs or external states.
  2. Stay home, stay safe from race conditions by avoiding shared mutable data.
  3. Hold on to effectively final or immutable instances.

These principles ensure your Runnable tasks run like well-oiled machines in a multithreaded context.

Tread carefully with Runnable

Here's a list of common tripwires when on the Runnable course:

  1. Case of the missing exceptions: Any thrown within a Runnable might disappear into thin air if not treated with care.
  2. Closet full of shared states: Accessing shared mutable data within a Runnable is like letting the cat out of the bag, with cat-astrophic consequences.
  3. Leaky faucets are a waste: Always do your housekeeping. Clean up resources like file handlers or threads to avoid resource leaks and deadlocks.

By avoiding these tripwires, you are all set to use Runnable in the most robust and reliable way.