Using same instance of ExecutorService in different threads is thread safe? - java

For example, I execute runnable block via ExecutorService instance and that runnable block execute some asynchronous code via the same ExecutorService instance.
So my code looks like:
final ExecutorService eService = Executors.newFixedThreadPool(nThreads);
eService.execute(new Runnable() {
public void run() {
eService.execute(new Runnable() {
public void run() {
System.out.println("Successfully created");
}
});
}
});
Is this code thread safe, because ExecutorService doesn't have a state?
In my real app I have some threads that created new threads inside them and I want to use one ExecutorService instance(maybe a bad practice?) with configurable thread pool size.
Is it a bad practice to do have one ExecutorService instance for different threads?
And if yes, maybe there are some alternatives?

It look fine. It is a good practice to reuse threads instead of spawning new ones (which is expensive) and one of possible implementations of such thread sharing can be usage of ExecutorService
Just keep in mind, that it will work for the code you have mentioned, It might break if you will try to await for the result of scheduled operation. This can lead to obvious deadlock when all the threads (from the pool) will be waiting for the result of the operation that awaits a free thread (in that pool) to execute it.

Related

Force re-use of thread by CompletableFuture

I am making critical use of:
CompletableFuture
.delayedExecutor(1, TimeUnit.MILLISECONDS).execute(() -> {});
From what I have read online, it's common for this to use a new thread for every call. I am wondering if there is a way to re-use a thread instead of creating new threads?
Update:
I wasn't clear - I want to use CompletableFuture, but I want CompletableFuture to reuse a certain thread, instead of managing its own threads.
I see this question:
CompletableFuture reuse thread from pool
but it recommends using an environment variable - I am wondering if there is a way to do this programmatically.
From what I have read online, it's common for this to use a new thread for every call.
(1) It's the case only if the machine doesn't support parallelism or you made it to not support it by setting the system property java.util.concurrent.ForkJoinPool.common.parallelism to 0 or 1.
8 processors
(2) If the machine does support parallelism, ForkJoinPool.commonPool() is used and the parallelism level is set, I guess, to the number of available processors (which can be determined by Runtime#availableProcessors).
In a scenario with 8 processors, 7-8 threads will probably be created to serve the common ForkJoinPool.
I want to use CompletableFuture, but I want CompletableFuture to reuse a certain thread, instead of managing its own threads.
A DelayedExecutor just submits tasks to the underlying Executor, which is either a ThreadPerTaskExecutor (1) or a ForkJoinPool (2).
Fortunately, you can manually specify an Executor which will be employed by the DelayedExecutor to delegate tasks to.
Executor delayedExecutor =
CompletableFuture.delayedExecutor(1, TimeUnit.MILLISECONDS, executor);
It gets us back to your previous question, where I pointed out that an Executor can be defined with a ThreadFactory.
Executor executor = Executors.newCachedThreadPool(YourThreadClass::new);
Executor new Thread is created for every set of tasks
An Executor is normally used instead of explicitly creating threads. For example, rather than invoking new Thread(new(RunnableTask())).start() for each of a set of tasks, you might use: for each of a set of tasks
Executor executor = anExecutor;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());
So if you want to reuse the threads, create a thread pool by using ExecutorService or ThreadPoolExecutor, so one of the threads from the pool will execute the runnable tasks.
If all the threads are busy, tasks will be queued up to a certain limit and after that will get rejected through a RejectedExecutionException.
Example
public class NewMain {
private static final ExecutorService ex = Executors.newFixedThreadPool(3);
public static void main(String[] args) {
Runnable r = () -> System.out.println(Thread.currentThread().getName());
ex.execute(r);
CompletableFuture<Void> c = CompletableFuture.runAsync(r, ex);
}
}
Jdk-8 Use CompletableFuture.runAsync and pass runnable, Executor
public static CompletableFuture runAsync(Supplier supplier,
Executor executor)
Returns a new CompletableFuture that is asynchronously completed by a task running in the given executor after it runs the given action.

Threadpool re-use of threads

I know this topic has been asked a lot, but im not sure about one detail.
Now threadpool doesnt let a thread die after completing a task, and reuses it later on as needed (as it is said here, here, etc)
But let say my runnable has variables in the constuctor -
MyRunnable(int a){
this.a = a;
}
then, when we try to run the Runnable with a Executors.newFixedThreadPool (or something similar), we say
executor.execute(new MyRunnable(a)); // executor being Executors.newFixedThreadPool
now if variable 'a' is different in every execute, can Threadpool really reuse it later?
I cant really understand how that would work, but i never seen 'Threadpool reuses threads except...', hence the confusion.
No, neither the Runnable you submit, nor the variables related to it, will be reused.
I think you mis-understood Thread and Runnable, they are different things. A Runnable is just normal object, execept its run method will be executed when you create a new thread with it. You can check this question.
The re-use of thread does not mean the re-use of Runnable, it means the thread keeps executing different Runnables.
When you create a Thread with a Runnable, and start this thread like this:
new Thread(new Runnable()).start()
the run() method of this Runnale will be executed, and after the run() exiting, this Thread will terminate too.
But, the Runnbale you submit to the ThreadPoolExecutor is not the one in code above to construct the thread.
Briefly, threads in ThreadPoolExecutor are created like this:
Runnable worker = new Runnable() {
#Override
public void run() {
Runnable firstTask = getFirstTask(); // the first runnable
firstTask.run();
Runnable queuedTask;
while ( (queuedTask = getTaskFromQueue()) != null) { // This could get blocked
queuedTask.run();
}
}
};
new Thread(worker).start();
Note, the Runnable used to initate the thread is not the one you submitted to the pool.
When you submit new Runnable, the thread pool will check if it need to create new thread(based on the argument like corePoolSize).
If it is necessary, then it create a new Worker with this Runnable as FirstTask, and create a new thread with this Worker and start it.
If not, then it put the Runnbale in a queue. When there are free threads, they will check this queue and take tasks from it.
So, from my point how the thread pool working algorithm would be similar and looks like below
while (check if the pool is not shutdown) {
Runnable task = pool.fetchTaskFromQueue(); // fetch the Task from the queue. In your case it object of MyRunnable class
task.run(); // call the run() of MyRunnable object
}
Thread pool resues the Thread, not the Runnable/ Callable implementation. So, as per thread pool, it does reuse your variable a.

new Thread(task).start() VS ThreadPoolExecutor.submit(task) in Android

In my Android project I had a lot of places where I need to run some code asynchronously (a web request, call to db etc.). This is not long running tasks (maximum a few seconds).
Until now I was doing this kind of stuff with creating a new thread, passing it a new runnable with the task. But recently I have read an article about threads and concurrency in Java and understood that creating a new Thread for every single task is not a good decision.
So now I have created a ThreadPoolExecutor in my Application class which holds 5 threads.
Here is the code:
public class App extends Application {
private ThreadPoolExecutor mPool;
#Override
public void onCreate() {
super.onCreate();
mPool = (ThreadPoolExecutor)Executors.newFixedThreadPool(5);
}
}
And also I have a method to submit Runnable tasks to the executor:
public void submitRunnableTask(Runnable task){
if(!mPool.isShutdown() && mPool.getActiveCount() != mPool.getMaximumPoolSize()){
mPool.submit(task);
} else {
new Thread(task).start();
}
}
So when I want to run an asynchronous task in my code I get the instance of App and call the submitRunnableTask method passing the runnable to it. As you can see, I also check, if the thread pool has free threads to execute my task, if not, I create a new Thread (I don't think that this will happen, but in any case... I don't want my task to wait in a queue and slow down the app).
In the onTerminate callback method of Application I shutdown the pool.
So my question is the following: Is this kind of pattern better then creating new Threads in code? What pros and cons my new approach has? Can it cause problems that I am not aware off yet? Can you advice me something better than this to manage my asynchronous tasks?
P.S. I have some experience in Android and Java, but I am far from being a concurrency guru ) So may be there are aspects that I don't understand well in this kind of questions. Any advice will be appreciated.
This answer assumes your tasks are short
Is this kind of pattern better then creating new Threads in code?
It's better, but it's still far from ideal. You are still creating threads for short tasks. Instead you just need to create a different type of thread pool - for example by Executors.newScheduledThreadPool(int corePoolSize).
What's the difference in behaviour?
A FixedThreadPool will always have a set of threads to use and if all threads are busy, a new task will be put into a queue.
A (default) ScheduledThreadPool, as created by the Executors class, has a minimum thread pool that it keeps, even when idle. If all threads are busy when a new task comes in, it creates a new thread for it, and disposes of the thread 60 seconds after it is done, unless it's needed again.
The second one can allow you to not create new threads by yourself. This behaviour can be achieved without the "Scheduled" part, but you will then have to construct the executor yourself. The constructor is
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
The various options allow you to fine-tune the behaviour.
If some tasks are long...
And I mean long. As in most of your application lifetime (Realtime 2-way connection? Server port? Multicast listener?). In that case, putting your Runnable in an executor is detrimental - standard executors are not designed to cope with it, and their performance will deteriorate.
Think about your fixed thread pool - if you have 5 long-running tasks, then any new task will spawn a new thread, completely destroying any possible gains of the pool. If you use a more flexible executor - some threads will be shared, but not always.
The rule of thumb is
If it's a short task - use an executor.
If it's a long task - make sure your executor can handle it (i.e. it either doesn't have a max pool size, or enough max threads to deal with 1 more thread being gone for a while)
If it's a parallel process that needs to always run alongside your main thread - use another Thread.
To answer your question — Yes, using Executor is better than creating new threads because:
Executor provides a selection of different thread pools. It allows re-use of already existing threads which increases performance as thread creation is an expensive operation.
In case a thread dies, Executor can replace it with a new thread without affecting the application.
Changes to multi-threading policies are much easier, as only the Executor implementation needs to be changed.
Based on the comment of Ordous I have modified my code to work with only one pool.
public class App extends Application {
private ThreadPoolExecutor mPool;
#Override
public void onCreate() {
super.onCreate();
mPool = new ThreadPoolExecutor(5, Integer.MAX_VALUE, 1, TimeUnit.MINUTES, new SynchronousQueue<Runnable>());
}
}
public void submitRunnableTask(Runnable task){
if(!mPool.isShutdown() && mPool.getActiveCount() != mPool.getMaximumPoolSize()){
mPool.submit(task);
} else {
new Thread(task).start(); // Actually this should never happen, just in case...
}
}
So, I hope this can be useful to someone else, and if more experienced people have some comments on my approach, I will very appreciate their comments.

How to interrupt ExecutorService's threads

When using the ExecutorService returned by Executors.newSingleThreadExecutor(), how do I interrupt it?
In order to do this, you need to submit() a task to an ExecutorService, rather than calling execute(). When you do this, a Future is returned that can be used to manipulate the scheduled task. In particular, you can call cancel(true) on the associated Future to interrupt a task that is currently executing (or skip execution altogether if the task hasn't started running yet).
By the way, the object returned by Executors.newSingleThreadExecutor() is actually an ExecutorService.
Another way to interrupt the executor's internally managed thread(s) is to call the shutdownNow(..) method on your ExecutorService. Note, however, that as opposed to #erickson's solution, this will result in the whole ThreadPoolExecutor becoming unfit for further use.
I find this approach particularly useful in cases where the ExecutorService is no longer needed and keeping tabs on the Future instances is otherwise unnecessary (a prime example of this being the exit(..) method of your application).
Relevant information from the ExecutorService#shutdownNow(..) javadocs:
Attempts to stop all actively executing tasks, halts the processing of
waiting tasks, and returns a list of the tasks that were awaiting
execution.
There are no guarantees beyond best-effort attempts to stop processing
actively executing tasks. For example, typical implementations will
cancel via Thread.interrupt, so any task that fails to respond to
interrupts may never terminate.
One proper way could be customizing/injecting the ThreadFactory for the ExecutorService and from within the thread factory, you got the handle of the thread created, then you can schedule some task to interrupt the thread being interested.
Demo code part for the overwrited method newThread in ThreadFactory:
ThreadFactory customThreadfactory new ThreadFactory() {
public Thread newThread(Runnable runnable) {
final Thread thread = new Thread(runnable);
if (namePrefix != null) {
thread.setName(namePrefix + "-" + count.getAndIncrement());
}
if (daemon != null) {
thread.setDaemon(daemon);
}
if (priority != null) {
thread.setPriority(priority);
}
scheduledExecutorService.schedule(new Callable<String>() {
public String call() throws Exception {
System.out.println("Executed!");
thread.interrupt();
return "Called!";
}
}, 5, TimeUnit.SECONDS);
return thread;
}
}
Then you can use below code to construct your ExecutorService instance:
ExecutorService executorService = Executors.newFixedThreadPool(3,
customThreadfactory);
Then after 5 seconds, an interrupt signal will be sent to the threads in ExecutorService.

Execute longtime threads in it's special order

Many time-consuming threads (500-900ms.) are created in the application.
They are to be executed in the order they have been created - one after another - not simultaneously. The execution should be processed in thread, that is not synchronized with main application thread.
I can't make small threads executed in an order, so I found a ThreadPoolExecutor, but think it's too heavy for my task. So I wrote my Executor class.
It works fine. You add a thread to the threadList and it start the Executor thread to execute small tasks, that can be added while execution.
Can you tell me it's drawbacks and maybe another better way to solve my problem.
import java.util.LinkedList;
import java.util.List;
public class SfourExecutor extends Thread implements Runnable {
private static List <Thread> threadList = new LinkedList<Thread>();
private static final SfourExecutor INSTANCE = new SfourExecutor();
public static List<Thread> getThreadList() {
return threadList;
}
public static void setThreadList(List<Thread> threadList) {
SfourExecutor.threadList = threadList;
}
public void addToThreadList(Thread thread) {
getThreadList().add(thread);
if (!this.isAlive()) {
this.start();
}
}
public static SfourExecutor getInstance() {
return SfourExecutor.INSTANCE;
}
private static class SfourHolder {
private static final SfourExecutor INSTANCE = new SfourExecutor();
}
SfourExecutor () {
}
#Override
public void run() {
LinkedList <Thread> tL = (LinkedList<Thread>) getThreadList();
while (!tL.isEmpty()) {
Thread t = tL.poll();
if (t!=null) {
t.start();
try {
t.join();
} catch (InterruptedException ex) {
}
}
}
}
}
Won't an Executor created via Executors.newSingleThreadExecutor() meet your requirements exactly? "Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time."
Don't create new Thread instances when you don't need to execute jobs concurrently. Even if you are working with legacy code that has implemented some logic in a Thread class, you should be able to execute them as Runnable instances to the executor.
If you insist on using your own executor, you should know that your current implementation is not thread-safe. LinkedList is not a concurrent data structure, and since any code in the process can add new jobs at any time, you have no way to ensure that all jobs are added to the list before your executor thread is started. Thus, changes to the list are not guaranteed to be visible to all of the threads that are working with it.
Why are you using threads instead of Runnables? Isn't it easier to have a list of Runnables and call run() on them instead than a list of thread and wait for each one to end?
Apart from this, your solution seems fine.
In both cases, I would only add some form of synchronization on addToThreadList and around the block that checks if there are tasks to execute in the run() method, since there is a possibility that the two pieces of code execute at the same time on the same linked list, which is not synchronized.
Actually, you should really consider using an Executor. I don't think you'll find it heavy:
int maxThreads = 1;
ExecutorService myService = Executors.newFixedThreadPool(maxThreads);
...
myService.execute(myRunnable);
Always avoid rewriting something that exists already. You'll avoid writing new bugs. For instance, your implementation is not Thread safe. 2 simultaneous calls to addToThreadList expose you too an illegalthreadstateexception.
Nice code, but Executors.newFixedThreadPool(nThreads) nice too. If your threads make long work (500-900ms) in your tasks - pool overhead not affect performance. And JIT and another JVM runtime optimization can work better with standard classes.
You have a problem in that once the thread list is empty, your processing thread will stop checking for new threads added to the list. Also, LinkedLists aren't safe for concurrent usage, so what one thread submits might not be seen by the executor thread (or worse, it might not show up the way you submitted it). If you used a LinkedBlockingQueue it would work better.
However, since you want everything to run in sequence, you don't need to create and start lots of new threads (which is pretty costly), you can just have one thread that runs lightweight Runnable tasks in order. ThreadPoolExecutor does this for you, and more, and it is also really easy to use if you take help from the Executors class (which uses ThreadPoolExecutors behind the scenes):
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(new Runnable(){
#Override
public void run(){
doSomethingThatTakesALongTime();
}
});
executorService.submit(new Runnable(){
#Override
public void run(){
doSomethingElseThatAlsoTakesALongTime();
}
});
Concurrency isn't easy, so I'd advice you to make use of the fact that Sun Oracle have experts employed full-time to write and maintain these libraries for you. That means you get more free time you can spend at the pub, with your family, or implementing new features for your customers.

Categories

Resources