Reputation: 3568
I'm writing a file that does a HUGE number of calls to different locations online (sadly that's part of a requirement)
My question is something like this:
Let's assume that I have a main method and want to call some other method:
public static void main(String args[]){
//how do I break stuff into threads here
Thread nameThread1 = new(fileName.DoMethod1(x))
Thread nameThread2 = new(fileName.DoMethod2(x))
Thread nameThread3 = new(fileName.DoMethod3(x))
Thread nameThread4 = new(fileName.DoMethod4(x))
Thread nameThread5 = new(fileName.DoMethod5(x))
}
//fileName.java
public static void doMethod1(object){
//Do Method Stuff
}
public static void doMethod2(object){
//Do Method Stuff
}
I've read some guides about how to implement it, but I'm still confused about the precise way to do this.
Can someone show me some examples if possible? Thanks!
Upvotes: 0
Views: 3383
Reputation: 2143
well, A lot of people suggested you to use Runnable but I would suggest you to use callable because Runnable, does not return a result and cannot throw a checked exception. To organize the code better and able to throw exceptions or return value from method use callable. Also for your purpose use some pool executor to do the job. Here is how I would say about the design, -
Write a callable class and based on request params call appropriate method,
private class GetAndProcessResponse implements Callable { private final Request request; private final CountDownLatch countDownLatch;
GetAndProcessResponse(final Request request, final CountDownLatch countDownLatch) {
this.request = request;
this.countDownLatch = countDownLatch;
}
public ProcessedResponse call() {
try {
// do a switch case on request params
// and call appropriate methods.
} finally {
countDownLatch.countDown();
}
}
}
Use countDownLatch to get job completion status.
Do not call join, since you need use executor service.
Use future.get(timeout) since it is a network job and need to cut after some time.
Upvotes: 0
Reputation: 1952
If you have to do a huge number of calls, the best solution is to instantiate a thread pool and use it for all your tasks. Later, you coild tune it depending on number of processors/cores your machine has. Here's a quite straightforward impementation using a ThreadPoolExecutor
:
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class GenericThreadPool {
private static final int CORE_POOL_SIZE = 3;
private static final int MAXIMUM_POOL_SIZE = 10;
private static final long KEEP_ALIVE_TIME = 10;
private ThreadPoolExecutor threadPool = null;
private final LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
private GenericThreadPool() {
this.threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS,
this.queue);
}
private static class LazyHolder {
public static final GenericThreadPool INSTANCE = new GenericThreadPool();
}
public static GenericThreadPool getInstance() {
return LazyHolder.INSTANCE;
}
public void execute(Runnable task) {
this.threadPool.execute(task);
}
public void shutdown() {
this.threadPool.shutdown();
}
}
To execute a task you just make a class that implements Runnable
interface, get the threadpool instance and run your job.
public class MyJob implements Runnable {
public void run(){
// Do your job here...
}
}
GenericThreadPool pool = GenericThreadPool.getInstance();
pool.execute(new MyJob());
Upvotes: 1
Reputation: 116858
You cannot call different methods like in your post. What you can do is to call different classes:
public static void main(String args[]){
Thread nameThread1 = new Thread(new Method1(x));
nameThread1.start();
Thread nameThread2 = new Thread(new Method2(x));
nameThread2.start();
Thread nameThread3 = new Thread(new Method3(x));
nameThread3.start();
Thread nameThread4 = new Thread(new Method4(x));
nameThread4.start();
Thread nameThread5 = new Thread(new Method5(x));
nameThread5.start();
}
public class Method1 implements Runnable {
private Object obj;
public Method1(Object obj) {
this.obj = obj;
}
//fileName.java
public void run(){
//Do Method Stuff
}
}
You should always consider using the create ExecutorService
code to manage jobs like this. For example:
// create a thread pool with 10 workers
ExecutorService threadPool = Executors.newCachedThreadPool();
threadPool.submit(new Method1(x));
threadPool.submit(new Method2(x));
...
// once we have submitted all jobs to the thread pool, it should be shutdown
threadPool.shutdown();
If you must use one class then you could start a single Runnable
that uses a switch or something:
public static void main(String args[]){
Thread nameThread1 = new Thread(new Method(1, x));
nameThread1.start();
Thread nameThread2 = new Thread(new Method(2, x));
nameThread2.start();
...
}
public class Method1 implements Runnable {
private int which;
private Object obj;
public Method1(int which, Object obj) {
this.which = which;
this.obj = obj;
}
//fileName.java
public void run(){
switch(which) {
case 1:
doMethod1(obj);
break;
case 2:
doMethod2(obj);
break;
...
}
}
private void doMethod1(Object obj){
...
}
private void doMethod2(Object obj){
...
}
}
But the executors or the separate Runnable
classes would be cleaner.
Upvotes: 8
Reputation: 20323
Thread
needs an instance of Runnable
, so what you can do is create a class which implements Runnable and you pass the command that it has to respond to, then depending upon the command you choose which method to call.
public class MyRunnable implements Runnable {
public MyRunnable(String commandToExecute){
this.command = commandToExecute;
}
public void run() {
//depending on command call specific methods.
}
}
One disadvantage of this approach is that your run method has too long a list of if else to check which method to invoke.
Benefit is that you don't create unnecessary class if all the methods are related to one class and placing them in separate classes doesn't make sense.
Another approach is to have separate class for every method as suggested by Gray, instead of you directly creating instance of specific class you can use Factory Pattern
to create and instance for you.
Upvotes: 1