I was playing with java multithreading code. I created a executor service with fixed thread pool. I am submitting two tasks sequentially. I tried to make the first task really long with the Thread.sleep. I was thinking these two tasks will run parallelly. However, when I run the program, the programs waits for sometime, then prints A B, means the compiler finished the first task at first before going to the second task. Actually, I was expecting, as the second task is a short task, it would be complete before the first task. Any explanation please?
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(10);
Map<String, String> map = new HashMap<>();
ReadWriteLock lock = new ReentrantReadWriteLock();
executor.submit(() -> {
lock.writeLock().lock();
try {
Thread.sleep(10000);
map.put("boo", "mar");
System.out.println("A");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.writeLock().unlock();
}
});
executor.submit(() -> {
lock.writeLock().lock();
try {
Thread.sleep(1);
map.put("foo", "bar");
System.out.println("B");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.writeLock().unlock();
}
});
executor.shutdown();
}
You are "locking" the writeLock BEFORE the first thread sleeps.. so the lock is actually locked for 10 seconds.. then it is unlocked. The second thread was waiting for 10 seconds to acquire the lock.
Sequence of events:
Thread 1: Starts
Thread 2: Starts
Thread 1: Acquire Lock and wait for 10 seconds.
Thread 2: Try to acquire lock (ends up waiting 10 seconds because it is already acquired by Thread 1).
Thread 1: Prints Data.
Thread 1: Unlocks lock.
Thread 2: Acquires lock.
Thread 2: Prints data.
Thread 2: Unlocks lock.
Try something like the below (it acquires the lock only when necessary.. IE: When doing a write operation or modification of the map):
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(10);
Map<String, String> map = new HashMap<>();
ReadWriteLock lock = new ReentrantReadWriteLock();
executor.submit(() -> {
try {
Thread.sleep(10000);
lock.writeLock().lock();
map.put("boo", "mar");
lock.writeLock().unlock();
System.out.println("A");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
executor.submit(() -> {
try {
Thread.sleep(1);
lock.writeLock().lock();
map.put("foo", "bar");
lock.writeLock().unlock();
System.out.println("B");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
executor.shutdown();
}
Related
I think Lock.lock() is not interruptible, while Lock lockInterruptibly() can be interrupted. So I tried:
public static void main(String[] args) throws InterruptedException {
Lock l = new ReentrantLock();
Thread t = new Thread(new Runnable() {
#Override public void run() {
l.lock();
System.out.println("Thread 3 start");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("lock is interrup")
e.printStackTrace();
} finally {
l.unlock();
}
System.out.println("Thread 3 end");
} // end run
});
t.start();
Thread.sleep(1000);
t.interrupt();
t.join();
}
On running it, it prints:
Thread 3 start
lock is interrupted
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at mygroup.UseLock$3.run(UseLock.java:42)
at java.lang.Thread.run(Thread.java:748)
Thread 3 end
Well I expected that Thread 3 is not interruptible because there's l.lock();
So where did I get wrong? What's indeed an non-interruptible thread?
Appreciate your explanations!
As noted in the comments, your test is flawed because the thread is not interrupted when l.lock() is called. In order to test this properly, you should additionally call l.lock() just before t.start(). This will cause the l.lock() call within thread t to block, and the interrupt will arrive while it is blocked, and since l.lock() does not allow interrupts, it should continue to block in spite of the interrupt. After sending the interrupt, your main thread can wait a second or two and then release the lock. In thread t You should then test to make sure that the thread has the interrupt status set immediately upon returning from l.lock(). Here is an example:
Lock l = new ReentrantLock();
// test Lock.lock()
Thread t = new Thread(() -> {
try {
l.lock();
} catch(InterruptedException ex) {
System.out.println("Lock.lock() was interrupted.");
}
if(Thread.interrupted()) {
System.out.println("Thread was interrupted and Lock.lock() was not interrupted.");
} else {
System.out.println("Thread was not interrupted");
}
l.unlock();
});
l.lock();
t.start();
Thread.sleep(1000);
t.interrupt();
Thread.sleep(1000);
l.unlock();
t.join();
// now test Lock.lockInterruptibly()
t = new Thread(() -> {
try {
l.lockInterruptibly();
} catch(InterruptedException ex) {
System.out.println("Lock.lockInterruptibly() was interrupted.");
}
if(Thread.interrupted()) {
System.out.println("Thread was interrupted and Lock.lockInterruptibly() was not interrupted.");
} else {
System.out.println("Thread was not interrupted");
}
l.unlock();
});
l.lock();
t.start();
Thread.sleep(1000);
t.interrupt();
Thread.sleep(1000);
l.unlock();
t.join();
This should print:
Thread was interrupted and Lock.lock() was not interrupted.
Lock.lockInterruptibly() was interrupted.
I have created ExecutorService and submitted a job. The job might be time-consuming. So I have given timeout as 2 seconds. If the execution takes more than 2 seconds, I want to kill that thread.
public void threadTest() {
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
executor.submit(() -> {
try {
String threadName = Thread.currentThread().getName();
Thread.sleep(7000);
System.out.println("process completed after 7 seconds");
} catch (Exception e) {
e.printStackTrace();
}
}).get(2, TimeUnit.SECONDS);
}catch (Exception e){
}
executor.shutdown();
}
public static void main(String[] args) throws Exception {
System.out.println("main start");
ThreadBreaker tb = new ThreadBreaker();
tb.threadTest();
System.out.println("main end");
}
output
main start
main end
process completed after 7 seconds
The function threadTest exited after 2 seconds as I expected. But the submitted job kept running. I want to stop the submitted task if it couldn't complete in a given timeout.
Once you have submitted a task to executorService you've got an Future object. And you can cancel execution by Future.cancel(true) call.
Keep in mind that canceling the active running task is possible when you have accurate InterruptException handling inside a task.
In the example above:
Thread.sleep(7000);
will raise an interrupted exception and you should not catch it (or if you catched it re-raise another exception)
When you use ExecutorService you cannot kill Threads by yourself. ThreadPool decides when to kill a Thread (typically it might happen if the Thread was interrupted).
In your case you should catch the TimeoutException and cancel the Future. If your "real" task is responsive to interruption(invoking and handling InterruptedException correctly) it will work. Otherwise you should check the Thread.currentThread().isInterrupted() status in a loop.
Your example code will look like :
public void threadTest() {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> submit = executor.submit(() -> {
try {
String threadName = Thread.currentThread().getName();
Thread.sleep(7000);
System.out.println("process completed after 7 seconds");
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); //preserve interruption status. based on this ThreadPool's interruption Policy will decide what to do with the Thread
}
});
try {
submit.get(2, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace(); //handle this
} catch (TimeoutException e) {
submit.cancel(true); //cancel the task
}
executor.shutdown();
}
Also remember that if you execute a task in a ThreadPool and you execute operations that might from InterruptedException in most cases you should preserve the interruption status.
I am using a Java based file conversion tool which converts PDF to DOCX, but sometimes while conversion it stuck, if input file size is more then 1 MB and start utilizing 100% CPU and more memory and keep running. I want to stop this continuous thread.
I know stop() function is deprecated.
Calling thread.interrupt(); is not helping, since thread is keep running.
There is no loop in the code ...so cannot check for interrupted flag in loop
How to Stop a running Thread t.
public class ThreadDemo implements Runnable {
Thread t;
PdfToDocConversion objPdfToDocConversion;
ThreadDemo() throws InterruptedException {
t = new Thread(this);
System.out.println("Executing " + t.getName());
// this will call run() fucntion
t.start();
Thread.sleep(2000);
// interrupt the threads
if (!t.interrupted()) {
System.out.println("Interrupted");
t.interrupt();
}
System.out.println(t.isInterrupted()); // true
System.out.println(t.getName());
System.out.println(t.isAlive()); /// still true
// block until other threads finish
try {
t.join();
} catch (InterruptedException e) {
}
}
public void run() {
objPdfToDocConversion = new PdfToDocConversion();
try {
objPdfToDocConversion.convertDocToPdf();//inside this function thread got stuck
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.print(t.getName() + " interrupted:");
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String args[]) {
try {
new ThreadDemo();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
You can build your own logic in killing the thread by the help of boolean flag.
public class RunningThread implements Thread {
private volatile boolean running = true;
public void run() {
while (running) {
try {
// Add your code here
} catch (InterruptedException e) {
if(!running){
break;
}
}
}
}
public void stopThread() {
running = false;
interrupt();
}
}
Here is the usecase:
RunningThread thread = new RunningThread();
thread.start(); // start the thread
thread.stopThread(); // stops the thread
The approach above is originally used by Google developers in on of there framework a.k.a Volley library.
Thread.interrupt() only sets a flag within the Thread object that the Thread should be interrupted. It does not cause the target Thread to throw an InterruptedException, instead code that can be interrupted must continually check that flag to see if someone has requested it be interrupted. That code then must handle it, usually by throwing an InterruptedException.
Some of the answers say about stopping the loop with volatile boolean isRunning but I do not see any loop in your example. Interrupting the thread does not actually interrupt it "right now". It just says "thread will be interrupted as soon as there will be such an opportunity". In your case I would suggest to close your PDF file and flag it with some boolean - then you can catch the IOException and if the flag is set - it means that you caused this situation and you can finish the thread.
I am using ExecutorService and its blocking the main program for some time but I don't want to block the main program.
Here is the code:
public class Test {
public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
ExecutorService executor = null;
try {
executor = Executors.newFixedThreadPool(1);
System.out.println("Start 1");
Runnable task = new Runnable() {
public void run() {
System.out.println("Start 2");
try {
Thread.sleep(7000);
System.out.println("Start 5");
} catch (Exception e) {
}
}
};
System.out.println("Start 3");
// executor.execute(task);
Future future = executor.submit(task);
Object result = future.get(9, TimeUnit.SECONDS);
System.out.println("Start 4");
} catch (Exception e) {
} finally {
System.out.println("finally");
executor.shutdownNow();
}
}
}
Output:
Start 1
Start 3
Start 2
Start 5
Start 4
finally
Currently it does not print Start 4 until and unless the thread completes the execution. What I am looking for is some mechanism where we can have a timeout and the thread runs in the background and does not block the main thread?
You are using future.get(9, TimeUnit.SECONDS); This will wait for 9 seconds, for the submitted thread to finish.
If you don't need the main program to wait and also don't require anything to be returned by the thread, then use the executor.execute call.
Here is the updated code...
ExecutorService executor = null;
try {
executor = Executors.newFixedThreadPool(1);
System.out.println("Start 1");
Runnable task = new Runnable() {
public void run() {
System.out.println("Start 2");
try {
Thread.sleep(7000);
System.out.println("Start 5");
}
catch (Exception e) {
}
}
};
System.out.println("Start 3");
executor.execute(task);
System.out.println("Start 4");
}
catch (Exception e) {
}
finally {
System.out.println("finally");
executor.shutdown();
}
}
You are not catching timeout exception in current code before printing Start 4 but you are catching Exception after `Start 4' line. So you are not getting desired output in case of timeout.
Change your code
from
Object result = future.get(9, TimeUnit.SECONDS);
to
try {
Object result = future.get(9, TimeUnit.SECONDS);
} catch (CancellationException ce) {
System.out.println("CancellationException ");
} catch (ExecutionException ee) {
System.out.println("ExecutionException ");
} catch (InterruptedException ie) {
System.out.println("InterruptedException ");
Thread.currentThread().interrupt(); // ignore/reset
}
With above code, you always get Start 4 irrespective of time-out of Future task.
Refer to afterExecute method in ThreadPoolExecutor documentation page for more details.
Regarding blocking of main thread, currently you are using blocking get() call on Future. If you don't want to block your main thread, change ExecutorService to ExecutorCompletionService and use new API as per documentation above page.
I have two threads running t1 and t2. When t2 notifies t1, immediately t2 should go to wait state. However, this is not possible as once it notifies t1, it should finish its current process and only after the end of the current thread execution, the t1 execution starts. But i would like to start t1 immediately after t2 notifies so that i can put t2 in wait state for t1 to notify inside the while loop. Is this possible with synchronized block?. I have tried the following code that does not work. I have also commented the coding lines to mention the way i would like to code.
public void passNo(int data)//thread t1
{
this.data1=data;
synchronized(thread2)
{
System.out.println("thread1 running");
data1=data1+100;
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("thread1 going to notify thread two");
thread2.notify();
/* try {
thread1.wait();
} catch (Exception e) {
e.printStackTrace();
}*/
}//sync
try {
Thread.sleep(1000);
} catch (Exception e) {}
System.out.println("im done, receiver go");
//}
}
public void ramos(int data)//thread t2
{
synchronized(thread1)
{
try{
System.out.println("I am thread 2 waiting for thread 1");
thread1.wait();//Problem-not notified ever by sender
System.out.println("Notified by sender thread");}
catch(InterruptedException ex){}
System.out.println("I am released");
n=obj.getInteger();
setInteger();
System.out.println("Notified");
}//sync
j++;
//}//while
}
class ClaObj
{
public static void main(String[] args)
{
Sender s=new Sender();
Receiver r=new Receiver();
r.classobj(s);
Thread thread1 = new Thread(s);
Thread thread2 = new Thread(r);
s.sendthrobj(thread1);
r.recvthobj(thread1);
thread1.start();
thread2.start();
}
}