Abstract: Just like inner classes, lambdas might also suffer from memory issues, but to a lesser extent. In this puzzle you need to figure out which lambdas are affected.
Welcome to the 247th edition of The Java(tm) Specialists' Newsletter, sent to you from the beautiful Island of Crete. It is the season for wild asparagus, which grows naturally underneath olive trees on our mountains. Healthy, crunchy and delicious. Eaten raw or boiled. Even though most people come for the beaches, Crete has far more interesting food to offer at this time of year.
javaspecialists.teachable.com: Please visit our new self-study course catalog to see how you can upskill your Java knowledge.
When someone with 315094 Twitter followers asks if I could post a Java puzzle, I am happy to oblige :) Here it is. Besides the "Hi from ... " messages, what other output do you see?
import java.util.concurrent.*; import static java.util.concurrent.TimeUnit.*; public class MemoryPuzzleWithLambdas { static class A { public Runnable get() { return new Runnable() { public void run() { System.out.println("Hi from A"); } }; } protected void finalize() throws Throwable { System.out.println("A finalized"); } } static class B { public Runnable get() { return () -> System.out.println("Hi from B"); } protected void finalize() throws Throwable { System.out.println("B finalized"); } } static class C { private int count = 0; public Runnable get() { return () -> System.out.println("Hi from C #" + ++count); } protected void finalize() throws Throwable { System.out.println("C finalized"); } } static class D { private static int count = 0; public Runnable get() { return () -> System.out.println("Hi from D #" + ++count); } protected void finalize() throws Throwable { System.out.println("D finalized"); } } static class E { private int count = ThreadLocalRandom.current().nextInt(); public Runnable get() { int count = this.count; return () -> System.out.println("Hi from E " + count); } protected void finalize() throws Throwable { System.out.println("E finalized"); } } static class F { public Runnable get() { return this::friendly; } public void friendly() { System.out.println("Hi from F"); } protected void finalize() throws Throwable { System.out.println("F finalized"); } } static class G { // Thanks Gray Watson for the suggestion public Runnable get() { return new MyRunnable(); } protected void finalize() { System.out.println("G finalized"); } private static class MyRunnable implements Runnable { public void run() { System.out.println("Hi from G"); } } } public static void main(String... args) { ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(); timer.scheduleAtFixedRate(new A().get(), 1, 1, SECONDS); timer.scheduleAtFixedRate(new B().get(), 1, 1, SECONDS); timer.scheduleAtFixedRate(new C().get(), 1, 1, SECONDS); timer.scheduleAtFixedRate(new D().get(), 1, 1, SECONDS); timer.scheduleAtFixedRate(new E().get(), 1, 1, SECONDS); timer.scheduleAtFixedRate(new F().get(), 1, 1, SECONDS); timer.scheduleAtFixedRate(new G().get(), 1, 1, SECONDS); timer.scheduleAtFixedRate(System::gc, 1, 1, SECONDS); } }
See if you can figure it out without first running the code :-)
Kind regards from Crete
Heinz
We are always happy to receive comments from our readers. Feel free to send me a comment via email or discuss the newsletter in our JavaSpecialists Slack Channel (Get an invite here)
We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.