Mimicking Go’s ‘go’ Keyword in Java and Groovy with Thread Pools

This article explains how to achieve Go‑style asynchronous execution in Java and Groovy by leveraging closures, the java.util.function.Supplier interface, custom thread‑pool wrappers, and Phaser‑based synchronization, complete with practical code examples and a custom ThreadFactory implementation.

FunTester
FunTester
FunTester
Mimicking Go’s ‘go’ Keyword in Java and Groovy with Thread Pools

Idea

Java supports closures, so we can recreate the effect of Go's go keyword by building an anonymous java.lang.Runnable implementation and handing it to a thread or thread pool. Groovy, which is fully compatible with Java syntax, can use the same approach with its groovy.lang.Closure type.

Java Implementation

Using java.util.function.Supplier (which has no parameters and returns a value) we wrap the asynchronous block and start a new thread:

package com.funtest.javatest;

import com.funtester.frame.SourceCode;
import java.util.function.Supplier;

public class Sync extends SourceCode {
    public static void main(String[] args) {
        sync(() -> {
            sleep(0.1);
            output("tester");
            return DEFAULT_CHARSET;
        });
        output("FunTester");
    }

    public static void sync(Supplier f) {
        new Thread(() -> {
            f.get();
        }).start();
    }
}

Console output demonstrates that the asynchronous block runs in a separate thread.

Groovy Implementation

Groovy simplifies the syntax further by using a Closure directly:

import com.funtester.frame.SourceCode

class Sync extends SourceCode {
    public static void main(String[] args) {
        sync {
            sleep(0.2)
            output(320)
        }
        output("FunTester")
    }

    static void sync(Closure f) {
        new Thread(f()).start()
    }
}

The output is similar to the Java version, confirming that Groovy can achieve the same lightweight async behavior.

Thread‑Pool Upgrade

To avoid creating too many raw threads, the closure is wrapped into a Runnable and submitted to a thread‑pool utility:

/**
 * Execute a code block asynchronously.
 * Java requires a return value; Groovy does not.
 */
public static void fun(Supplier f) {
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            f.get();
        }
    };
    ThreadPoolUtil.executeSync(runnable);
}

A custom ThreadFactory is provided to give threads meaningful names:

/**
 * Create a custom ThreadFactory that names threads "FT-XX".
 */
static ThreadFactory getFactory() {
    if (FunFactory == null) {
        synchronized (ThreadPoolUtil.class) {
            if (FunFactory == null) {
                FunFactory = new ThreadFactory() {
                    @Override
                    Thread newThread(Runnable runnable) {
                        Thread thread = new Thread(runnable);
                        int increment = threadNum.getAndIncrement();
                        String name = increment < 10 ? "00" + increment :
                                      increment < 100 ? "0" + increment :
                                      "" + increment;
                        thread.setName("FT-" + name);
                        return thread;
                    }
                };
            }
        }
    }
    return FunFactory;
}

Multi‑Thread Synchronization

When tasks need to be coordinated, java.util.concurrent.Phaser is used. The wrapper registers the current thread, runs the supplied block, and deregisters on completion:

/**
 * Execute a code block asynchronously and synchronize with a Phaser.
 */
public static void fun(Supplier f, Phaser phaser) {
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                phaser.register();
                f.get();
            } catch (Exception e) {
                logger.warn("Error executing async method!", e);
            } finally {
                phaser.arriveAndDeregister();
            }
        }
    };
    ThreadPoolUtil.executeSync(runnable);
}

IDE Support

IntelliJ IDEA’s Live Templates can generate the boilerplate for the custom thread factory and other snippets, making the code concise and repeatable.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaconcurrencyThreadPoolAsyncGroovyclosurePhaser
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.