0

In the below example, I am using the field number in IntStream.range(0, 10).forEach(number -> new Thread(r).start()); even though it is not being used. Is there a way to rewrite it so that I do not have to use the unused number variable?

    import javax.annotation.concurrent.NotThreadSafe;
    import java.util.stream.IntStream;
    
    public class LearnThreads {
        public static void main(String[] args)  {
            UnsafeThreadClass counter = new UnsafeThreadClass();
            Runnable r = () -> {
                try {
                    System.out.println(counter.getValue() + " : Thread - " +Thread.currentThread());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
            IntStream.range(0, 10).forEach(number -> new Thread(r).start());
        }
    }
    
    
    @NotThreadSafe
    class UnsafeThreadClass {
        private int value;
    
        public synchronized int getValue() throws InterruptedException {
            Thread.sleep(1000);
            return value++;
        }
    }
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
Punter Vicky
  • 15,954
  • 56
  • 188
  • 315
  • 2
    Nope, not really. We need to pass along a `Consumer` when using the `stream`-API. – Turing85 Dec 31 '22 at 23:05
  • 2
    At the moment, not if you want to use a lambda. There is a proposal [JEP 302: Lambda Leftovers](https://openjdk.org/jeps/302) which would allow using underscore for unused lambda parameters, but it's not implemented yet as of Java 19. – prunge Dec 31 '22 at 23:10
  • You can opt for naming the parameter `ignore` – Bohemian Jan 01 '23 at 05:54

2 Answers2

8

No; you must specify a name for the consumer's parameter, however why use a stream at all?

This is simpler and more readable:

for (int i = 0; i < 10; i++) {
    new Thread(r).start();
}

If you must use a Stream, try limit() instead:

Stream.generate(() -> new Thread(r)).limit(10).forEach(Thread::start);

But there's an ugly producer in there.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
3

As an alternative you can create a lightweight virtual List to a using static method Collections.nCopies() (which behaves like a regular List but it's not baked by a real data structure, basically it's a wrapper around the provided reference and its memory footprint is tiny).

Here's how you can fire 10 Runnable tasks using Stream API and nCopies():

Runnable r = // initializing the task
        
Collections.nCopies(10, r).stream().map(Thread::new).forEach(Thread::start);

The same can be done using without Streams using Iterable.forEach():

Runnable r = // initializing the task

Collections.nCopies(10, r).forEach(task -> new Thread(task).start());
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46