I want to close all thread which I started previously.
Thread.currentThread() gives me current thread, but what about others? How can I get them?
I think Thread.activeCount() returns the count of active threads in thread's thread group, but I does not use ThreadGroup,
I just started threads using Thread thread = new Thread(new MyRunnable()).
So how can I achieve this?
thanks in advance...
You can use an ExecutorService instead which combines a thread pool with a queue of tasks.
ExecutorService service = Executors.newCachedThreadPool();
// or
ExecutorService service = Executors.newFixedThreadPool(THREADS);
// submit as many tasks as you want.
// tasks must honour interrupts to be stopped externally.
Future future = service.submit(new MyRunnable());
// to cancel an individual task
future.cancel(true);
// when finished shutdown
service.shutdown();
You can simply keep references to all the threads somewhere (like a list) and then use the references later.
List<Thread> appThreads = new ArrayList<Thread>();
Every time you start a thread:
Thread thread = new Thread(new MyRunnable());
appThreads.add(thread);
Then when you want to signal termination (not via stop I hope :D) you have easy access to the threads you created.
You can alternatively use an ExecutorService and call shutdown when you no longer need it:
ExecutorService exec = Executors.newFixedThreadPool(10);
...
exec.submit(new MyRunnable());
...
exec.shutdown();
This is better because you shouldn't really create a new thread for each task you want to execute, unless it's long running I/O or something similar.
If you wish to keep using the Thread object directly and not using ready-to-use thread services from java.util.concurrent you should keep a references to all started thread (for example, put them in a List) and when wish to to close them, or interrupt them to stop, loop over the List.
Related
The Problem:
I am parsing a large log file (around 625_000_000 lines) and saving it into the database.
public class LogScheduler {
static int fileNumber = 1;
public Importer(IRequestService service) {
this.service = service;
}
#Override
public void run() {
try {
service.saveAll(getRequestListFromFile("segment_directory/Log_segment_"+fileNumber+".txt"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
The method that runs this thread is:
public void scheduledDataSave() throws InterruptedException {
int availableCores = Runtime.getRuntime().availableProcessors();
String directory = "segment_directory";
int filesInDirectory = Objects.requireNonNull(new File(directory).list()).length;
ExecutorService executorService = Executors.newFixedThreadPool(availableCores);
for (int i = 1; i <= filesInDirectory; i++) {
executorService.execute(new Importer(service));
}
executorService.shutdown();
}
Inserting the Thread.sleep(); method after the executorService.execute(new Importer(service)); sleeps after the execution of every thread, and not 8 threads like it should since they are in the Executorservice
And I have no idea why that happens since it should not behave like that.
From what I understand, the ExecutorService should run 8 threads in parallel, finish them, sleep, and start the pool again.
How to "sleep" after every 8 threads?
Sleeping the thread submitting tasks does not sleep the submitted tasks
Your question is not clear, but apparently centers around your expectation that adding a Thread.sleep after each call to executorService.execute would sleep all the threads of the executor service.
for ( int i = 1 ; i <= filesInDirectory ; i++ ) {
executorService.execute( new Importer( service ) ); // Executor service assigns this task to one of the background threads in its backing pool of threads.
Thread.sleep( Duration.ofMillis( 100 ).toMillis() ) ; // Sleeping this thread doing the looping. *Not* sleeping the background threads managed by the executor service.
}
Your expectation in incorrect.
That Thread.sleep is sleeping the thread doing the for loop.
The executor service has its own backing pool of threads. Those threads are not affected by a Thread.sleep is some other thread. Those background threads will only sleep if you call Thread.sleep within the code running on each of those threads.
So you are feeding the first task to the executor service. The executor service immediately dispatches that work to one of its backing threads. That task is immediately executed (if a thread is available immediately, and not otherwise occupied by previous tasks).
After assigning that task, your for loop sleeps for a hundred milliseconds, in this example code shown here. While the for loop is asleep, no further tasks are being assigned to the executor service. But while the for loop is asleep, the submitted task is executing on a background thread. That background thread is not sleeping.
Eventually, your for loop thread wakes, assigns a second task, and goes back to sleep. Meanwhile the background thread executes at full speed ahead.
So sleeping the thread submitting tasks does not sleep tasks already submitted.
Waiting for submitted tasks to complete
Your title asks:
ExecutorService should wait until batch of taksk is finished before starting again
After submitting your tasks, call shutdown and awaitTermination on your executor service. After those calls, your code blocks, waiting until all the submitted tasks are are completed/canceled/failed.
ExecutorService executorService = Executors.newVirtualThreadExecutor() ;
… submit tasks to that executor service …
executorService.shutdown() ;
executorSerivce.awaitTermination() ; // At this point, the flow-of-control blocks until the submitted tasks are done.
System.out.println( "INFO - Tasks on background threads are done. " + Instant.now() );
I would suggest using the ExecutorService#submit method rather than ExecutorService#execute method. The difference is that the first method returns a Future object. You can collect these Future objects as you submit tasks to the executor service. After the shutdown & awaitTermination, you can examine your collection of Future objects to check their completion status.
Project Loom
If Project Loom succeeds, such code will be a bit simpler and more clear. Experimental builds of Project Loom technology are available now, based on early-access Java 17. The Loom team seeks feedback now.
With Project Loom, ExecutorService becomes AutoCloseable. This means we can use try-with-resources syntax to automatically call a new close method on ExecutorService. This close method first blocks until all the tasks are completed/canceled/failed, then shuts down the executor service. No need to call shutdown nor awaitTermination.
By the way, Project Loom also bring virtual threads (fibers). This is likely to dramatically increase the performance of your code because it involves much blocking for storage i/o and database access.
try (
ExecutorService executorService = Executors.newVirtualThreadExecutor() ;
)
{
… submit tasks to that executor service …
}
// At this point, with Project Loom technology, the flow-of-control blocks until the submitted tasks are done.
// Also, the `ExecutorService` is automatically closed/shutdown by this point, via try-with-resources syntax.
System.out.println( "INFO - Tasks on background threads are done. " + Instant.now() );
With Project Loom, you can collect the returned Future objects in the same manner as discussed above to examine completion status.
You have other issues in your code. But you've not disclosed enough to address them all.
How to "sleep" after every 8 threads?
So if you are doing something like this, then it isn't doing what you think.
for (int i = 1; i <= filesInDirectory; i++) {
executorService.execute(new Importer(service));
Thread.sleep(...);
}
This causes the thread which is starting the background jobs to sleep and does not affect the running on each of the jobs. I believe what you are missing is to wait for the thread-pool to finish:
executorService.shutdown();
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
This waits for all of the jobs in the thread-pool to complete before continuing.
One more thing. I use executorService.submit(...) versus execute(...). Here's a description of their difference. For me, one additional difference is that any exceptions thrown by tasks run with execute(...) cause the running thread to terminate and possibly be restarted. With submit(...) it allows you to get that exception if needed and stops the threads from having to be respawned unnecessarily.
If you explain a bit more about what you are trying to accomplish, we should be able to help.
Code:
//List all threads:
Set<Thread> runningThreads = Thread.getAllStackTraces().keySet();
System.out.println(runningThreads.toString());
//Thread creation:
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(this);
//Thread termination:
executorService.shutdownNow();
//List all threads:
Set<Thread> runningThreads = Thread.getAllStackTraces().keySet();
System.out.println(runningThreads.toString());
I would expect the list that gets printed out to be exactly the same both times but what I'm getting is a print out of the thread that was created included in the results
How do I completely destroy a thread so that it's nowhere to be found?
shutdownNow() attempts to stop the running thread, but as its API documentation says:
This method does not wait for actively executing tasks to terminate. Use awaitTermination to do that.
So the thread may still be running when the code after the call to shutdownNow() returns. Note also that you need to make sure that the task running in the thread actually terminates; shutdownNow() is not going to kill the thread, it will just try to interrupt it.
As the documentation says, call executorService.awaitTermination(...) after calling shutdownNow() to wait until the thread has stopped.
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 requirement in multi-threaded environment in java. The problem is like;
I have suppose 10 different task, and I want to assign all these 10 task to 10 different threads. Now the finish time for these tasks could be different. And there is some finishing or clearance task which should be performed when all these 10 threads are finished. In other words i need to wait until all threads are finished and then only I can go ahead with my further code execution.
Please let me know if any more details required here.
Thansk,
Ashish
Sounds like an ideal job for CountDownLatch.
Initialize it with 10 counts and when each thread finishes its job, it counts down one.
When all 10 threads have finished, the CountDownLatch will let the original thread run, and it can perform the cleanup.
And fire up an ExecutorService with 10 fixed threads to run the tasks.
CyclicBarier (JDK java.util.concurrent) of size 10 is perfect solutuon for you. With CyclicBarier you can wait for 10 threads. If all t hreads achieve barier then you can go further.
Edit: CyclicBarier is almost the same as CountDownLatch but you can reuse barier invoking reset() method.
Whilst CountDownLatch and CyclicBarier do the job of synchronizing multiple threads and performing one action when all threads reach the required point, they require all tasks to actively use this feature. If you are interested in the finishing of the entire task(s) only, the solution can be much simpler: add all tasks to a Collection and use the invokeAll method of an ExecutorService which returns when all tasks have been completed. A simple example:
Callable<Void> simpleTask=new Callable<Void>() {
public Void call() {
System.out.println("Performing one job");
return null;
}
};
List<Callable<Void>> list = Collections.nCopies(10, simpleTask);
ExecutorService es=Executors.newFixedThreadPool(10);
es.invokeAll(list);
System.out.println("All completed");
If each thread terminates after it is finished, you could just use the join() statement. A simple example can be found in the Essential Java Tutorials.
ArrayList<Thread> myThreads = new ArrayList<Thread>();
for (int i = 0; i < 10; i++){
//MyTaskRunnable is a Runnable with your logic
Thread t = new Thread(new MyTaskRunnable());
myThreads.add(t);
}
for(Thread t : myThreads){
t.start();
}
//here all threads are running
for(Thread t : myThreads){
t.join();
}
//here all threads have terminated
Edit:
The other answers all have their merits and are very useful in practice, the join() is however the most basic of the constructs. The CyclicBarrier and CountDownLatch versions allow your threads to continue running after reaching the synchronization point, which can be necessary in some cases. The ExecutorService is more suited to many tasks needing to be executed on a fixed number of threads (aka a thread pool), to create an ExecutorService for just 10 tasks is a bit drastic.
Finally, if you are new to learning Java or are taking a course on concurrency, you should try out all the variants and see what they do. The join is the most basic of these constructs and will help you understand you what is going on. Also it is the basic model supported by most other languages.
I have a java application that sends requests to the server and returns me the response. The requests are run on separate threads each.
What I want to do is maintain 5 threads at a time (hence, 5 requests going at a time). Also, if a thread finishes, I want to start a new thread so that 5 threads are running at all times.
Initially I thought I could use join when calling the thread, but realized that will block my main thread.
Is there a way to get this done? I haven't programmed in Java much and am open to any suggestions/advice.
I would use an ExecutorService
Executor exec = Executors.newFixedThreadPool(5);
for(String url: urls)
exec.submit(new UrlTask(urls));
// when finished
exec.shutdown();
This will perform up to 5 tasks at once.
It seems you are looking for something like ExecutorService with fixed thread pool.
ExecutorService pool = Executors.newFixedThreadPool(5);
You shouldn't try to write this from scratch using Thread.
I'd recommend setting up an Executor pool and doing producer/consumer with a BlockingDeque.