Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What the difference between ExecutorService's execute and thread.run in running threads concurrently in Java?

I'm new to this concurrent programming in java and came up with following scenarios where I'm getting confusion which to use when.

Scenario 1: In the following code I was trying to run threads by calling .start() on GPSService class which is a Runnable implementation.

int clientNumber = 0;
ServerSocket listener = new ServerSocket(port);

while (true) {
            new GPSService(listener.accept(), clientNumber++, serverUrl).start();
} 

Scenario 2: In the following code I was trying to run threads by using ExecutorService class as shown

int clientNumber = 0;
ServerSocket listener = new ServerSocket(port);
while(true) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.execute(new GPSService(listener.accept(), client++, serverUrl));

        executor.shutdown();
        while (!executor.awaitTermination(1, TimeUnit.SECONDS)) {
            // Threads are still running
            System.out.println("Thread is still running");
        }
        // All threads are completed
        System.out.println("\nThread completed it's execution and terminated successfully\n");              
}

My Questions are
Which is the best practice to invoke a thread in concurrent programming?
What will be result(troubles) I'll end up with when I use first or second?
Note: I've been facing an issue with the first scenario where the program is getting hanged after every few days. So, is that issue related/expected when I use first method.?
Any good/helpful answer will be appreciated :) Thank you

like image 611
Kishore Kumar Korada Avatar asked Jun 20 '15 11:06

Kishore Kumar Korada


1 Answers

There are no big differences in the two scenario you posted, except from managing thread termination in Scenario2; you always create a new thread for each incoming request. If you want to use ThreadPool my advice is not to create one for every request but to create one for each server and reuse threads. Something like:

public class YourClass {

//in init method or constructor 
ExecutorService executor = Executors....;// choose from newCachedThreadPool() or newFixedThreadPool(int nThreads) or some custom option


int clientNumber = 0;
ServerSocket listener = new ServerSocket(port);
while(true) {

    executor.execute(new GPSService(listener.accept(), client++, serverUrl));

}

This will allow you to use a thread pool and to control how many threads to use for your server. If you want to use a Executor this is the preferred way to go.

With a server pool you need to decide how many threads there are in the pool; you have different choices but you can start or with a fixed number or threads or with a pool that tries to use a non busy thread and if all threads are busy it creates a new one (newCachedThreadPool()). The number of threads to allocate depends form many factors: the number of concurrents requests and it durations. The more your server side code takes time the more you need for additional thread. If your server side code is very faster there are very high chances that the pool can recycle threads already allocated (since the requests do not come all in the same exact instant).

Say for example that you have 10 request during a second and each request lasts 0.2 seconds; if the request arrive at 0, 0.1, 0.2, 0.3, 0.4, 0.5, .. part of the second (for example 23/06/2015 7:16:00:00, 23/06/2015 7:16:00:01, 23/06/2015 7:16:00:02) you need only three threads since the request coming at 0.3 can be performed by the thread that server the first request (the one at 0), and so on (the request at time 0.4 can reuse thread used for the request that came at 0.1). Ten requests managed by three threads.

I recommend you (if you did not it already) to read Java Concurrency in practice (Task Execution is chapter 6); which is an excellent book on how to build concurrent application in Java.

like image 129
Giovanni Avatar answered Sep 21 '22 15:09

Giovanni