AngryCoder
AngryCoder

Reputation: 496

Function as a function parameter in Java

I have a class, with Thread as superclass, I pass a function as a parameter and this class just execute that function. This class uses it to create threads, so I can execute any function in a thread without having to create a different class.

public class ThreadEjecucionLambda extends Thread {
Runnable funcion;
public ThreadEjecucionLambda(Runnable funcion)
{
    this.funcion=funcion;
}
public void run()
{
    funcion.run();
}
}

Now, to create several threads of a same method I use a 'for' block, for example:

for(Computer computer: Persistencia.getListComputers())
                            {
                                ThreadEjecucionLambda hilolambda=new ThreadEjecucionLambda(()->logica.EnciendeMonitor(computer.getNombrePC()));
                                hilolambda.run();
                            }

What I want to achieve is to generalice the previous 'for' so that I can execute a method,to which I will pass ,as parameters, (following the example) a list of 'Computers' and a function. This method will execute the 'for' block and will create a thread for each 'Computer, so I will pass as a parameter the previous function to the thread and that function will have, as a parameter, the 'Computer'. What I want to get is something like this (WARNING: IT'S WRONG):

    public void EjecutaHilosLambdaSegundo(ArrayList<Computer> listapcs,Runnable funcion)
{
    for(Computer computer: listapcs)
    {
        ThreadEjecucionLambda hilolambda=new ThreadEjecucionLambda(funcion(computer));
        hilolambda.run();
    }
}

I hope I have explained myself well because it's a very confusing problem.

Upvotes: 1

Views: 112

Answers (2)

JB Nizet
JB Nizet

Reputation: 691865

Thread already has a constructor taking a Runnable as argument, and executing it when you start it, so your subclass is useless and confusing. Not only that, but you never actually start any thread. So you could just run the Runnable directly, without creating any Thread or ThreadEjecucionLambda.

If I understand correctly, you want to execute the same function, taking a Computer as argument, on a list of Computers.

You don't need a Thread to do that. All you need is a Consumer<Computer>:

public consumeAllComputers(List<Computer> computers, Consumer<? super Computer> function) {
    computers.forEach(function);
}

But, as you see, this method is useless, since you could just call forEach on the List directly.

So, suppose you want to print the name of each computer in a list, you would use

computers.forEach(computer -> System.out.println(computer.getName());

Don't reinvent the wheel!

Upvotes: 2

kagmole
kagmole

Reputation: 2165

For the synchronous solution, look at @JB Nizet answer.


Asynchronous solution

First, your ThreadEjecucionLambda class is not creating thread, because to start a new thread, you need to call the start() method of Thread.

public class ThreadEjecucionLambda extends Thread {

    Runnable funcion;

    public ThreadEjecucionLambda(Runnable funcion)
    {
        super(funcion);
        this.funcion = funcion;
    }
    public void run()
    {
        super.start();
    }
}

Second, this class is meaningless! Thread is already working that way.

Third, Runnable as is does not accept argument. What you actually need to do is create your own Runnable that takes a Computer as an argument.

public class MyRunnable implements Runnable {

    Computer computer;

    public MyRunnable(Computer computer)
    {
        this.computer = computer;
    }

    @Override
    public void run()
    {
        // Do what you want cause a pirate is-
        // Erm do what you want with your computer object
    }
}

And then use it for your above method.

public void EjecutaHilosLambdaSegundo(ArrayList<Computer> listapcs, MyRunnable myRunnable)
{
    for(Computer computer: listapcs)
    {
        Thread myThread = new Thread(myRunnable);
        myThread.start();
    }
}

Upvotes: 1

Related Questions