I am using following code snippet in our code.
ExecutorService executor = Executors.newFixedThreadPool(4);
while(loop 50 times){
//In the extreme case I will have 50 threads and only 4 will be active and remaining are in queue
MyThread myThread = new MyThread();
executor.execute(myThread);//Each Thread process 100,000 records and put in a file
}
executor.shutdown();
while (!executor.isTerminated()) {
}
Here are my questions:
It is hanging at second while loop. What might be the reason?
Is there any way to terminate Entire thread pool after certain interval?
Can I terminate a thread after certain time interval?
Please help me in fixing this.
1.It is hanging at second while loop. What might be the reason?
The reason for hanging could be because of very few threads compared to the amount of records that needs to be processed and stored in file. If each thread is supposed to process 100,000 records and put in file then 50 thread tasks shared by 4 threads will have to process 5,000,000 records with 50 files. So better to increase the number of threads and check. Also note down time taken by each thread to effectively measure if you are reducing the time taken overall by increasing the number of fixed pool threads.
2.Is there any way to terminate Entire thread pool after certain interval?
Yes below code shows that:-
executor.shutdown();
executor.awaitTermination(60, TimeUnit.SECONDS); // blocks/waits for certain interval as specified
executor.shutdownNow(); // Forcefully terminate entire thread pool after the above time.
3.Can I terminate a thread after certain time interval?
Yes if effectively the reason for terminating a thread is to stop what task it is doing. To achieve this we need to get a reference to the future and wait conditionally for period of time before we forcefully cancel the task and interrupt the thread carrying out the task.
Map<String, Future> tasks = new HashMap<String, Future>();
while(i++ < 50){
//In the extreme case I will have 50 threads and only 4 will be active and remaining are in queue
Thread myThread = new Thread();
tasks.put("Thread"+i ,executor.submit(myThread));//Each Thread process 100,000 records and put in a file
}
// say you want to terminate Thread2 after 60 seconds
Future thread2Task = tasks.get("Thread2");
thread2Task.get(60, TimeUnit.SECONDS);
thread2Task.cancel(true); // boolean whether you want to interrupt the thred forcefully
ExecutorServise will have a pool of Threads to execute your Runnable tasks, you defined the size of the pool to be 4, I would change that to be the number of cpus in the machine:
int threadCount = Runtime.getRuntime().availableProcessors();
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
Also, it appears that you are sending Threads to the executor to execute them in one of the available threads in it's pool, It's redundant, you might change your MyThread to a Runnable task.
Related
How can I implement FIFO queue of threads(tasks to do) and executing the threads one by one?
I mean for example, take the first thread and run it, and the second must wait for the end of execution of the first thread.
At the same time I must be able to add threads(tasks) to the queue.
Create a FixedThreadPool with only one thread and submit tasks to it. They will be executed one after the other, like in a FIFO queue:
ExecutorService es = Executors.newFixedThreadPool(1); // one thread only
// ...
for(Runnable r : myRunnables) {
es.submit(r);
}
As Vakh said, use an ExecutorService to run the threads, however I would recommend using a SingleThreadExecutor. The SingleThreadExectutor is guaranteed to execute threads sequentially because unlike a FixedThreadPool it can not be reconfigured to use a different number of threads.
ExecutorService es = Executors.newSingleThreadExecutor(); // one thread only
// ...
for(Runnable r : myRunnables) {
es.submit(r);
}
You can also call Thread.join() to tell the current thread to block exectution until the other thread dies.
Thread t = new Thread(myRunnable);
t.join(); //Wait until t dies
There are variations of join which will set a maximum wait time
if you want all your threads to run at the same time but you don't want them to use a specific resource or task, then you can use Synchronized Methods
I have a ThreadPoolExecutor:
ThreadPoolExecutor service = new ThreadPoolExecutor(N_THREADS, N_THREADS, 0L, TimeUnit.MILLISECONDS, blockingQueue, rejectedExecutionHandler);
The service executes threads implementing the Runnable interface. Each thread processes a file on disk. I found that after several hours, two threads (or cores depending on what htop shows in Linux) were running and had been running for 13 hours. What's even worse is that the remaining cores showed no activity as if they were waiting for the two threads to complete.
Questions:
1 - I have read a lot on how this problem may be resolved but nothing conclusive. As far as I can work out, you CANNOT stop a Runnable using the ThreadPoolExecutor because it is an independent thread that just runs. Using the Future framework:
Future<?> f = f.get(submittedtask,XX)
allows you to set a timeout and fetch the future result, but get blocks all the threads effectively making the implementation serial. Is it possible to interrupt a Runnable after a given time using the threadpoolexecutor, get the thread back to the pool so it can pickup a new task and carry on.
2 - My big concern is why, using htop, I see two threads/cores running and no other core/thread are running despite many tasks are still waiting to execute (i.e. there are many files left to process). Any insight?
You could create a second scheduled thread pool to which you would submit cancellation tasks for each of the returned Futures. Each of these tasks after a given timeout would check if it's associated Future is done and if not, cancel it. Cancellation would trigger thread interruption, so you might need to support it in your tasks by checking the interrupted flag: Thread.interrupted().
The size of this second thread pool could be minimal, i.e. 1 as this job takes minimum of CPU time.
Code example:
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
...
while(...){
final Future<?> f = pool.submit(...);
service.schedule(new Runnable() {
#Override
public void run() {
if(!f.isDone()){
f.cancel(true);
}
}
}, 1, TimeUnit.MINUTES);
}
service.awaitTermination(1, TimeUnit.MINUTES);
service.shutdown();
You can tell a thread that you wish to interrupt:
An interrupt is an indication to a thread that it should stop what it is doing and do something else.
You can interrupt your thread with Future.cancel(true). It's in your responsibility to implement the Runnable in a manner that it obeys that wish by checking its Thread.interrupted() state.
In order to see details about process thread run:
ps -eLf | grep <PROCESS_PID>
Since htop shows you the running processes list, where each process has at least one thread.
From javadoc for ThreadPoolExecutor:
When a new task is submitted in method execute(java.lang.Runnable)
.... If there are more than corePoolSize but less than
maximumPoolSize threads running, a new thread will be created only if
the queue is full.
How can I make ThreadPool that will start new thread instead of submitting task to queue in this situation?
Example:
I have thread with corePoolSize=5 and maxPoolSize=10 and unbounded queue.
Suppose corePoolSize threads is busy right now, and new task is arrived - pool must start new thread and execute new task.
Suppose maxPoolSize threads is busy right now, and new task is arrived - pool must persist task into queue, and first free thread must take this task and execute.
If you want a thread pool with a maximum size where the tasks are queued only when all the threads are busy.
ExecutorService service = Executors.newFixedThreadPool(numberOfThreads);
The cached thread pool which will not queue tasks, but will create a new thread as required. It will re-use a thread if one is free.
ExecutorService service = Executors.newCachedThreadPool();
I've just posted this exact question and provided an answer there:
How to get the ThreadPoolExecutor to increase threads to max before queueing?
Sorry to not have found this question beforehand otherwise I would have just answered it.
To summarize the answer, I extend LinkedBlockingQueue to have it always return false for queue.offer(...) which will add an additional threads to the pool, if necessary. If the pool is already at max threads and they all are busy, the RejectedExecutionHandler will be called. It is the handler which then does the put(...) into the queue.
There is sample code in my answer. Again, sorry for the dup.
If you want to start new Thread each time regardless of availability of idle threads, then you need not ThreadPool at all - just create and start new Thread manually. This is better because your threads would die immediately after they do their work, and in the ThreadPool they would wait some time for new job but never get it, thus only wasting memory.
I use ThreadPoolExecutor to manage a thread pool. What we want are:
if the pool has less than corePoolSize threads, kick off a new thread for a new task;
if the pool has more than corePoolSize threads and all are busy, kick off a new thread for a new task until maxPoolSize is reached. In that case, reject the task;
keep corePoolSize number of threads alive even if they are idling, excess threads will die if they have been idle for more than keepAliveTime
According the Java6 docs, keepAliveTime should work as above. But in my test code, it doesn't work consistently.
When I set keepAliveTime to 0, it works fine, always keeping core threads alive and terminating excess threads when they finish;
but, as shown below, when I set keepAliveTime to a positive value, it seems that it terminate ALL idle threads, no matter they are core threads or not.
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 500, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>());
assertFalse("Not allow core threads to time out.", executor.allowsCoreThreadTimeOut());
Task task_1 = new Task(1000);
Task task_2 = new Task(1000);
Task task_3 = new Task(1000);
executor.execute(task_1);
executor.execute(task_2);
executor.execute(task_3);
Thread.sleep(1050L);
assertEquals("Completed 3 tasks.", 3, executor.getCompletedTaskCount());
assertEquals("Three threads are in the pool.", 3, executor.getPoolSize());
Thread.sleep(600L);
//////// This assertion will fail: **expected <2> but was <0>**
assertEquals("Two threads are in the pool.", 2, executor.getPoolSize());
////----
private static class Task implements Runnable {
private long sleepMillis;
public Task(final long sleepMillis) {
this.sleepMillis = sleepMillis;
}
public void run() {
try { Thread.sleep(sleepMillis);
} catch (Exception e) { System.out.println(e); }
}
}
Is there any misunderstanding about keepAliveTime or getPoolSize? If getPoolSize is not the correct API, how can I get to know the number of "alive" threads (idle or busy)?
Thanks in advance.
Java 7 passes the test. Apparently java 6 has a bug. Reading its code, all threads can exit when the queue is empty, that is definitely wrong for core threads.
#arosima keepAliveTime only takes effect on excess threads rather than core threads. Core threads will be always kept in the pool. I also wrote another answer to understand, hope it helpful.
I am pretty sure the pool size is a target size. I don't think there are any guarantees about shutting down threads (there is no background checker) I think its just a hint. Idle threads give next to no overhead.
I have 2 classes that implement Runnable.I need to create 10 threads to execute them.I use the following code.
ExecutorService es = Executors.newFixedThreadPool(10);
Runnable r=new TestThread1();
Runnable r1=new TestThread2();
es.execute(r);
es.execute(r1);
but since only 2 runnables exist,only 2 threads are being used to execute.how shud i increase the no of threads
Threads will be created as you submit more jobs to the executor. If the number of submitted jobs exceed 10 (in this case), the new jobs will be queued. When threads become free they will be used to run the queued jobs. If you want the executor to create 10 threads, you need to submit 10 jobs:
for (int i = 0; i < 5; ++i) {
if (!es.isShutdown()) {
es.submit(new TestThread1());
es.submit(new TestThread2());
}
}
One Runnable can only run on one Thread. It doesn't get split up across multiple threads automatically.
If you want to utilise your entire thread pool, create more runnable objects.
Executors.newFixedThreadPool(size) returns ThreadPoolExecutor instance.
JavaDoc of ThreadPoolExecutor says: ” When a new task is submitted in method ThreadPoolExecutor.execute, and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle.”
That is, you have to execute 10 threads to fill the pool.