For loop works different in Groovy and Java For loop works different in Groovy and Java multithreading multithreading

For loop works different in Groovy and Java


A Java closure closes over the immutable value in f when created, while the Groovy closure closes over the mutable variable f.

So once the Groovy loop finishes, f contains 5 and threads that happen to run after that will print 5.

Java closures can close over a variable reference that's final or “effectively final” meaning that it’s final in all but name. See Java 8: Lambdas, Part 1. That's what inner classes can do plus some useful convenience.

Groovy closures are very different objects, and they predate Java closures. See Groovy Closures, where the example { ++item } modifies a variable from the enclosing scope.

Groovy defines closures as instances of the Closure class. It makes it very different from lambda expressions in Java 8. Delegation is a key concept in Groovy closures which has no equivalent in lambdas. The ability to change the delegate or change the delegation strategy of closures make it possible to design beautiful domain specific languages (DSLs) in Groovy.

Bottom line Groovy aims to be the dynamic language with the best "impedance match" to Java, but now that Java has lambdas, the two languages continue to diverge. Caveat programmer.


It is not an issue with the "Closure implementation" in Groovy.

It is with your misunderstanding of what a Closure is.

First of all, it is not the same as an anonymous method (class) or Lambda (Java 8+).
It is the same as a JavaScript closure.

A closure has full read/write access to local variables that are in scope, meaning variables defined in the enclosing method, but outside the closure. Those variables exist and can be updated by any code with access to them, and they continue to exist after the method defining them exits (returns).

You really should read much more about closures, either in Groovy or JavaScript documentation and examples. JavaScript is rife with use of closures, so you'll find lots of documentation on the subject.

Here's a short intro:

def a() {    def myval = 0    return { x -> myval += x } // <-- Returns a closure}def f = a()print f(5)print f(7)

This will print 5 and 12, because the variable myval exists as long as the closure assigned to f stays alive.

Or here is the JavaScript version: https://jsfiddle.net/Lguk9qgw/

In contrast, Java cannot do that, because Java doesn't have closures, not even with the new Lambdas. Java's anonymous classes, and their Lambda equivalent, require all outside variables to be invariant, i.e. final, whether explicitly defined that way, or inferred by the compiler (new in Java 8).

This is because Java in reality copies the value, and requiring the value to be final ensures that you don't notice, unless you disassemble the generated bytecode.

To show this, these 5 Java examples all do the same thing, functionally, e.g. calling test1().applyAsInt(5) will return 12:

// Using Lambda Expressionpublic static IntUnaryOperator test1() {    final int f = 7;    return x -> x + f;}// Using Lambda Blockpublic static IntUnaryOperator test2() {    final int f = 7;    return x -> { return x + f; };}// Using Anonymous Classpublic static IntUnaryOperator test3() {    final int f = 7;    return new IntUnaryOperator() {        @Override public int applyAsInt(int operand) { return operand + f; }    };}// Using Local Classpublic static IntUnaryOperator test4() {    final int f = 7;    class Test4 implements IntUnaryOperator {        @Override public int applyAsInt(int operand) { return operand + f; }    }    return new Test4();}// Using Nested Classprivate static final class Test5 implements IntUnaryOperator {    private final int f;    Test5(int f) { this.f = f; }    @Override public int applyAsInt(int operand) { return operand + this.f; }}public static IntUnaryOperator test5() {    final int f = 7;    return new Test5(f);}


I really don't know the reason for loop specified in question, but followin code snippet works like a charm:

["one","two","three","four"].each { tid ->    Thread.start {        println "Thread $tid says Hello World!"    }}