if i have got such java code:
public static void main(String[] args)
{
for(int i = 0;i<100;i++)
{
Future<?> f = ThreadPoolManager.getInstance().schedule(new START(), 500);
f.cancel(true);
}
}
private class START implements Runnable
{
#Override
public void run()
{
System.out.println(1);
}
}
And run it in debug, i can see that all of those threads(after cancel) are still running, so are they taking my memory too? And if yes, how can i destroy those Threads completely?
cancel(true) calls interrupt() on your thread, nothing more. So, you need to handle it properly in your run() method. For your simple case your threads will finish their execution and their objects will be cleared by GC.
Related
I want to spawn a Java thread from my main java program and that thread should execute separately without interfering with the main program. Here is how it should be:
Main program initiated by the user
Does some business work and should create a new thread that could handle the background process
As soon as the thread is created, the main program shouldn't wait till the spawned thread completes. In fact it should be seamless..
One straight-forward way is to manually spawn the thread yourself:
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
runYourBackgroundTaskHere();
}
};
new Thread(r).start();
//this line will execute immediately, not waiting for your task to complete
}
Alternatively, if you need to spawn more than one thread or need to do it repeatedly, you can use the higher level concurrent API and an executor service:
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
runYourBackgroundTaskHere();
}
};
ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(r);
// this line will execute immediately, not waiting for your task to complete
executor.shutDown(); // tell executor no more work is coming
// this line will also execute without waiting for the task to finish
}
Even Simpler, using Lambda! (Java 8) Yes, this really does work and I'm surprised no one has mentioned it.
new Thread(() -> {
//run background code here
}).start();
This is another way of creating a thread using an anonymous inner class.
public class AnonThread {
public static void main(String[] args) {
System.out.println("Main thread");
new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Inner Thread");
}
}).start();
}
}
And if you like to do it the Java 8 way, you can do it as simple as this:
public class Java8Thread {
public static void main(String[] args) {
System.out.println("Main thread");
new Thread(this::myBackgroundTask).start();
}
private void myBackgroundTask() {
System.out.println("Inner Thread");
}
}
I have a long running Runnable object and I wanted to provide a more graceful interrupt mechanism than having to call interrupt on the thread the object is running on.
The before code:
public class MyRunnable implements Runnable {
public void run() {
while(!Thread.currentThread().isInterrupted()) {
//do stuff
}
}
}
public class MyClass {
public static void main(String[] args) {
Runnable myRunnable = new MyRunnable();
Thread t = new Thread(myRunnable, "myRunnableThread");
t.start();
//do stuff
t.interrupt();
//do stuff
}
}
And the new code:
public class MyRunnable implements Runnable {
private Thread myThread = null;
public void run() {
myThread = Thread.currentThread();
while(!myThread.isInterrupted()) {
//do stuff
}
}
public void shutdown() {
if (myThread != null) {
myThread.interrupt();
//do other shutdown stuff
}
}
}
public class MyClass {
public static void main(String[] args) {
Runnable myRunnable = new MyRunnable();
Thread t = new Thread(myRunnable, "myRunnableThread");
t.start();
//do stuff
myRunnable.shutdown();
//do stuff
}
}
My question is, are there possible side effects or unknowns that holding a reference to your own thread, and providing limited access to that thread through public methods (as above) could cause? This is assuming that no-one ever calls the run() method directly, that it is always started from a new thread.
And I'm aware that I could use a volatile or atomic Boolean in the run() and shutdown() methods for communicating intent to shutdown, I'm more interested in learning than a solution. But solutions are still welcome!
For me your first approach is much better as less error prone and more "standard". But actually what you try to implement already exists (which proves that it makes sense and that it is not a bad practice but it is not easy to make it properly), it is called FutureTask, instead of shutdown you have cancel(boolean mayInterruptIfRunning) with true as value of mayInterruptIfRunning if you want to interrupt the thread running the task, I quote the javadoc:
Attempts to cancel execution of this task. This attempt will fail if
the task has already completed, has already been cancelled, or could
not be cancelled for some other reason. If successful, and this task
has not started when cancel is called, this task should never run. If
the task has already started, then the mayInterruptIfRunning
parameter determines whether the thread executing this task should be
interrupted in an attempt to stop the task.
For example:
// Task that will only sleep for 1 sec and print a message on interrupted
FutureTask<Void> myRunnable = new FutureTask<>(
new Callable<Void>() {
#Override
public Void call() throws Exception {
try {
System.out.println("Sleep");
Thread.sleep(1_000L);
} catch (InterruptedException e) {
System.out.println("Interrupted !!!");
throw e;
}
return null;
}
}
);
new Thread(myRunnable, "myRunnableThread").start();
// Wait long enough to make sure that myRunnableThread is sleeping
Thread.sleep(500L);
// Cancel the task and interrupt myRunnableThread
myRunnable.cancel(true);
Output:
Sleep
Interrupted !!!
It already has a reference:
Thread.currentThread()
From the javadoc:
Returns a reference to the currently executing thread object.
I have written a small multithreading program.
public class NewThread implements Runnable {
Thread t;
public NewThread() {
t = new Thread(this, "Thread created by Thread Class.");
System.out.println("Created by constuctor:"+ t);
t.start(); // This will call run, because t has context as this
}
#Override
public void run() {
System.out.println("run() method called.");
}
public static void main(String[] args) {
new NewThread();
}
}
This is how the book says to write it. However, I never get the run() method called statement in the console. Thus, it seems run() is never called. How can this be true?
Edit: Yes, it is bad practice to start a Thread from constructor, but that is not affecting the question. (I am getting so many down votes for that)
run() is never called by Thread.start() method
You code actually works on my system but that it doesn't work on your's, demonstrates that you have a classic race condition.
Inside of main(), the NewThread is constructed but the Java language says that it can reorder operations so that the operations in a constructor can happen after the constructor finishes. So it is possible that main() might finish before the NewThread has actually been started which can result in the JVM shutting down without running the thread.
Because of instruction reordering, you should never have a thread auto-start itself inside of the constructor. See: Why not to start a thread in the constructor? How to terminate?
You should instead do:
public NewThread() {
t = new Thread(this, "Thread created by Thread Class.");
System.out.println("Created by constuctor:" + t);
// don't start here
}
public void start() {
// start in another method
t.start();
}
public void run() {
System.out.println("run() method called.");
}
...
public static void main(String[] args) {
NewThread nt = new NewThread();
nt.start();
}
Since the NewThread has the same daemon status as your main thread (which is non-daemon) the JVM will not shutdown until nt.run() completes.
I have the following piece of code which I expected to print "DONE" at the end. But when I ran, "DONE" was never printed and the JVM in fact never terminated.
What did I do wrong?
// File: Simple.java
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Simple {
public static void main(String[] args) throws Exception{
doTest(3);
}
private static void doTest(final int times) {
ScheduledExecutorService tp = Executors.newScheduledThreadPool(times);
Thread[] runnables = new Thread[times];
for (int i = 0; i < runnables.length; ++i) {
runnables[i] = new Thread(new MyRunnable());
}
// schedule for them all to run
for (Thread t : runnables) {
tp.schedule(t, 1, TimeUnit.SECONDS);
}
try {
tp.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
System.out.println("DONE!");
}catch (InterruptedException e) {
e.printStackTrace();
}
}
static class MyRunnable implements Runnable {
#Override
public void run() {
System.out.println("hello world");
}
}
}
There are two things that you're doing wrong here.
First off, if you're using an ExecutorService, you shouldn't then also be creating your own threads. Just submit Runnables to the executor directly - the executor service has its own collection of threads, and runs anything you submit on its own threads, so the threads you created won't even get started.
Second, if you're done with an ExecutorService, and are going to wait until it's terminated, you need to call shutdown() on the executor service after you submit your last job.
Executors.newScheduledThreadPool(times) uses Executors.defaultThreadFactory() for its ThreadFactory.
Here is the documentation
When a Java Virtual Machine starts up, there is usually a single
non-daemon thread (which typically calls the method named main of some
designated class). The Java Virtual Machine continues to execute
threads until either of the following occurs:
The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception
that propagates beyond the run method.
So, here is what you had; but I changed 3 things.
Added the shutdown hook
Made the schedule delayed by an extra second for each to demo that the shutdown is being called even before some of the threads are being called to run by the scheduler.
Lastly, you were telling it to wait forever using the Long.MAX. But I think you were doing it because the shutdown feels like it would shutdown now. But it won't.
public static void main(String[] args) throws Exception {
doTest(3);
}
private static void doTest(final int times) {
ScheduledExecutorService tp = Executors.newScheduledThreadPool(times);
Thread[] runnables = new Thread[times];
for (int i = 0; i < runnables.length; ++i) {
runnables[i] = new Thread(new MyRunnable());
}
// schedule for them all to run
int i = 1;
for (Thread t : runnables) {
tp.schedule(t, i++, TimeUnit.SECONDS);
}
System.out.println("Calling shutdown");
tp.shutdown();
}
static class MyRunnable implements Runnable {
#Override
public void run() {
System.out.println("hello world");
}
}
Hope that answers your question. Now, you're kinda duplicating stuff.
If you are going to use the executerservice, you should just tell it to schedule stuff for you.
public static void main(String[] args) throws Exception {
doTest(3);
}
private static void doTest(final int times) {
ScheduledExecutorService tp = Executors.newScheduledThreadPool(times);
for (int i = 0; i < times; ++i) {
tp.schedule(new MyRunnable(), 1, TimeUnit.SECONDS);
}
System.out.println("Calling shutdown");
tp.shutdown();
}
static class MyRunnable implements Runnable {
#Override
public void run() {
System.out.println("hello world");
}
}
You forgot to shutdown your ExecutorService:
tp.shutdown(); // <-- add this
tp.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
Also I should mention that creating Threads to use them as Runnables is not only meaningless, but can be misleading as well. You should really use Runnable instead of Thread for runnables variable.
Runnable[] runnables = new Runnable[times];
I have two classes. In class A, I have the run() method looped forever, while in the class B, i have the threadpool.
My question is, From Class B, how can I control and stop the thread executing run() method in class A , I have tried forceshutdown, threadExecutor.shutdownNow(), But it isnt working.
The loop seems to go on forever.
Here is example piece of code:
public class A implements Runnable {
public void run() {
while (true) {
System.out.println("Hi");
}
}
}
public class B {
public static void main(String[] args) {
int noOfThreads = 1;
A ThreadTaskOne = new A();
System.out.println("Threads are being started from Class B");
ExecutorService threadExecutor = Executors.newFixedThreadPool(noOfThreads);
threadExecutor.execute(ThreadTaskOne);
threadExecutor.shutdownNow();
System.out.println("B Ends, no of threads that are alive : " + Thread.activeCount());
}
}
As #MadProgammer said, your "infinite" loop needs to pay attention to Thread.isInterrupted. e.g. (very schematic)
public void run() {
while (!Thread.isInterrupted()) {
doSomethinginTheLoop1();
blah...blah...blah
// if the loop is very long you might want to check isInterrupted
// multiple times for quicker termination response
doSomethingInTheLoop2();
}
// now, here's a decision of what you do
// do you throw an InterruptedException or trust others to check interrupted flag.
// read Java COncurrency in Practice or similar...
}
The documentation on ExecutorService#shutdownNow() says -
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.
And your thread doesn't seem to care if it has been interrupted.
So check if it has been interrupted
while (Thread.currentThread().isInterrupted())
instead of just doing
while (true)
May be below is useful for you.
public static class A implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("Hi");
}
}
}