WorkerThread, how to pass an undefined method to be executed..?

I’m not even sure if the thread title makes sense. But essentially, I’m trying to use a scheduled executor to execute an undefined method.

This is the pseudo class:


import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * A simple worker thread. This should be used for things such as loading game assets,
 * or constructing a new region for your game.. without putting the stress on the render Processor,
 * or optional LogicThread.
 */
public class WorkerThread {
	
	public WorkerThread(Method method) { // pseudo
		ExecutorService executorService = Executors.newFixedThreadPool(1);
		executorService.execute(new Runnable() {
		    public void run() {
				method(); // pseudo
		    }
		});
		executorService.shutdown();
	}

}

It’s part of an abstract lwjgl wrapper, which I’ve been working on for a little over a month now. And have a handful of followers who use it religiously to power their games. But I’ve never done anything like THIS specifically so I’m lost :expressionless:


public WorkerThread(Runnable r) {
      ExecutorService executorService = Executors.newFixedThreadPool(1);
      executorService.execute(r);
      executorService.shutdown();
}

Creating a new thread pool each time you want to run something is a terrible idea though.
(And why is this a constructor?)

Alright, well what would be the most efficient way of going about this? A lot of people specifically are having issues loading game regions and constructing their random generated content / loading static map data. I don’t want to do anything that would be less than ethical

Method is part of java reflect , you call it using method.invoke() , if it has any parameters then you must pass them and if it is off a different instance than the current class that must be passed as an object for instance. method.invoke(instance); , this could be called as new_worker(mymethod, this)

Here is an example that I use in my game , allows you to bind render functions and other processes to a main tick.

public Encapsulated_method(Method method, Object[] parameters,
			Object instance) {
		this.method = method;
		this.parameters = parameters;
		this.instance = instance;
	}

	public void call() {
		if(instance == null){
			return;
		}
		if(method == null){
			return;
		}
		if (parameters != null) {
			try {
				method.invoke(instance, parameters);
			} catch (IllegalAccessException | IllegalArgumentException
					| InvocationTargetException e) {
				e.printStackTrace();
			}
		} else {
			try {
				method.invoke(instance);
			}
			catch (IllegalAccessException | IllegalArgumentException
					| InvocationTargetException e) {
				e.printStackTrace();
			}
		}
	}

And to call it for an example



	new Encapsulated_method(method,null,instance);
//where null is the parameters

Just do the normal thing and have a big thread pool somewhere that you hand Runnables/Callables to and get Futures from. Shut down the pool when your app exists or is otherwise appropriate.

Also refrain from misusing reflected methods. Just let the user pass in a runnable…

Excellent details! Thank you very much. Appreciated :slight_smile:

Like cylab said, I also don’t really understand why would you not just use a simple Runnable interface for this purpose and want to hack stuff like that.

I’m reading each and every reply from this thread, and refining my original snippet. Wouldn’t have posted for public help and then ignored it :wink:

Also note that requesting execution of one task and then immediately awaiting on the Future is pretty much equivalent to simply Runnable.run(). Don’t over complicate it if you don’t need some kind of actual asyncronicity.
(Now ExecutorService.invokeAll(), on the other hand is pretty nice)

Seems like with the information you’ve all provided, I’ll have to do a little more research as well. But you’ve all put me in the right direction so kudos :slight_smile:

Would it maybe be better to create something a tad more abstract, instead of passing variables off to a separate executor? Here’s an example from a jPCT powered application I wrote a few years ago, using jPCT’s worker instance

		/**
		 * Load prop models and spawns
		 */
		Worker worker = new Worker(1);
		worker.add(new WorkLoad() {
			public void doWork() {
				propManager = new PropManager(fileStorage, world, terrain);
			}
			public void done() { }
			public void error(Exception arg0) { }
		});
		worker.waitForAll();
		worker.dispose();

You create another thread and then wait for it?

But I don’t see how that is useful, those 10 lines are equivalent to
[icode]propManager = new PropManager(fileStorage, world, terrain);[/icode]

Aren’t they?

I would also say that that is less abstract.

BurntPizza, I think his example was just showing a slimmed down version of it. I would assume that he would add multiple tasks and then do waitForAll(). Although I may be wrong.

So then use ExecutorService.invokeAll().

So the scheduled executor code you and I have pasted would be the best route? And by abstract, I just meant, instead of passing variables into a secondary class that maybe it would be better to wrap them locally (where they exist) using the worker thread.
Sorry for wording that so weird.

You still haven’t explained what you are actually trying to do, so I can only speculate as to what the best way to do things is and instead give the most general (abstract) solution, having an ES instance and telling it to execute tasks.

Actually the biggest problem is usually not the thread execution, but getting the result back to the GL thread: With google guava, you would probably do something like this:


ListeningExecutorService pool = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
Futures.addCallback(
	pool.submit(new Callable<Chunk>() {
		public Chunk call() {
			return loadChunk();
		}
	},
	new FutureCallback<Chunk>() {
		public void onSuccess(Chunk loaded) {
			// do something with loaded
		}
		public void onFailure(Throwable thrown) {
			// handle a failure somehow
		}
	},
	myGameloopExecutor // execute the callbacks on the gameloop
);

You would need to implement your own GameloopExecutor by minimally implement the AbstractExecutorService class and store the Runnables and Callables you get in a Queue that you could execute at the start of the gameloop.

This is solved by Future.