Rohit Malish
Rohit Malish

Reputation: 3229

Submitting method into ExecutorService Java

So I have this code here, that adds my "NamePrinter" runnable class as ExecutorService tasks. Everything works fine, but I'd like to get rid of that extra class. So I am asking is there a way to submit method to ExexutorService?

Here is the code that I currently have:

public void start(){
        Collection<Future<?>> futures = new LinkedList<>();
        final ExecutorService es = Executors.newFixedThreadPool(poolSize);

        for (int i = 0; i < 10; i++) {
        futures.add(es.submit(new NamePrinter(name)));
        }

        es.shutdown();
}

But I'd like it to be something like this:

public void start(){
            Collection<Future<?>> futures = new LinkedList<>();
            final ExecutorService es = Executors.newFixedThreadPool(poolSize);

            for (int i = 0; i < 10; i++) {
            futures.add(es.submit(namePrint(i+"name"))); // This code doesn't work, I just made it so you could understand what I mean.
            }

            es.shutdown();
    }

public void namePrint(String name){  // I'd like this to be the task that ExecutorService runs.

System.out.println(name);

}

Is this something that is possible to achieve?

Upvotes: 3

Views: 4331

Answers (4)

Renann
Renann

Reputation: 608

In this specific case, I think you'll not be able to do exactly what you want, because the run method of Runnable interface doesn't take any arguments. However, you can use lambda expressions since Java 8. So you have few options now:

1 - Define the method on-the-fly

final String name = "whatever";

exServ.execute(() -> {            
    System.out.println(name);
});

2 - Define a static method and then use static method reference

public static void printName()
{
    System.out.println(ClassNameX.name);
}

exServ.execute(ClassTest::printName);

3 - Create an instance of your NamePrinter class - which doesn't need to implement the Runnable interface - to store the parameters and then use instance method reference.

NamePrinter np = new NamePrinter("testName");

exServ.execute(np::namePrint);

Upvotes: 2

Muki
Muki

Reputation: 3641

There are some options for this:

  1. Using anonymous class

    es.submit { new Runnable() {
     public void run() {
      //do your stuff here
     }
    });
    
  2. Use languages which support closures like Scala. However the API must support this, which ExecutorService doesn't.

  3. Wait for Java 8 which will introduce closures.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1502536

The closest you can come as an anonymous inner class:

for (int i = 0; i < 10; i++) {
    final int x = i;
    futures.add(es.submit(new Runnable() {
        @Override public void run() {
            namePrint(x + "name");
        }
    }));
}

Upvotes: 5

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340903

You are essentially asking: is Java supporting functions as first class citizens (sometimes it is refered as closures or lambdas) - no, you can't do this in Java. You can in Groovy, Scala, JavaScript, C#... but not in Java.

Your NamePrinter class (probably implementing Runnable or Callable) is the closest you can get in Java and this is the Java way (or you can use anonymous inner class).

Upvotes: 3

Related Questions