The main class trying to create 4 threads
After running the threads, each thread tries to lock. And when one thread gets the lock, the rest will wait to unlock.
In my case, once Thread 0 found that the resource is locked, and then Thread 0 went in the wait state, then why again Thread 0 tries to lock the resource.
package com.test.thread;
public class LockImplementation {
public static void main(String[] args) {
MyNewThread myThread1 = new MyNewThread(1);
MyNewThread myThread2 = new MyNewThread(2);
MyNewThread myThread3 = new MyNewThread(3);
MyNewThread myThread4 = new MyNewThread(3);
myThread1.start();
myThread2.start();
myThread3.start();
myThread4.start();
}
}
class Lock {
private boolean isLocked = false;
private Thread lockingThread = null;
int count = 0;
public synchronized void lock() throws InterruptedException {
if (isLocked) {
System.out.println("trying to lock by thread " +
lockingThread.getName());
wait();
}
System.out.println("Locked by thread " +
Thread.currentThread().getName());
isLocked = true;
lockingThread = Thread.currentThread();
}
public synchronized void unLock() {
if (this.lockingThread != Thread.currentThread()) {
throw new IllegalMonitorStateException("Calling thread has not locked this lock");
}
isLocked = false;
lockingThread = null;
notify();
}
}
class MyNewThread extends Thread {
int thNo;
private static Lock lock;
public MyNewThread(int thNo) {
Thread.currentThread().setName(thNo + "");
this.thNo = thNo;
lock = new Lock();
}
#Override
public void run() {
System.out.println("start running thread no " +
Thread.currentThread().getName());
try {
lock.lock();
Thread.sleep(10000);
lock.unLock();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end running thread no " +
Thread.currentThread().getName());
}
}
Why is the same thread trying to lock the resource?
This happens because when first time you enter lock method you set your locking thread as first that enters it. Next threads when call lock() see that isLocked is true and wait, but locking thread still the same and it doesn't update.
Related
Create a synchronous multithreaded system to determine the total of all integers or fractions in three text files. If a stream is blocked, it must display its name as "LOCKED". Why count only one file (Thread with lock)? What the programs display:Thread-0 Locked!
Thread-2 Locked!
123.321 322099, it's only for one file
import java.io.*;
import java.util.*;
import java.util.concurrent.locks.*;
public class Dispatcher {
public static void main(String[] args) throws InterruptedException {
SumOfDigits sumOfDigits = new SumOfDigits();
Thread thread = new Handler(new File("text.txt"), sumOfDigits);
Thread thread2 = new Handler(new File("text2.txt"), sumOfDigits);
Thread thread3 = new Handler(new File("text3.txt"), sumOfDigits);
thread.start();
thread2.start();
thread3.start();
thread.join();
thread2.join();
thread3.join();
System.out.println(sumOfDigits.resultDouble + " " + sumOfDigits.resultInt);
}
}
class SumOfDigits {
double resultDouble;
int resultInt;
Lock lock = new ReentrantLock();
void sum(File file) {
try (Scanner sc = new Scanner(file)) {
int tempInt = 0;
double tempDouble = 0;
while (sc.hasNext()) {
String num = sc.next();
if (num.contains(".")) {
tempDouble += Double.parseDouble(num);
} else {
tempInt += Integer.parseInt(num);
}
}
boolean flag = lock.tryLock();
if (flag) {
try {
resultDouble += tempDouble;
resultInt += tempInt;
} catch (Exception e) {
} finally {
lock.unlock();
}
} else {
System.out.println(Thread.currentThread().getName() + " Locked!");
}
} catch (Exception e) {
}
}
}
class Handler extends Thread {
File file;
SumOfDigits sumOfDigits;
Handler(File file, SumOfDigits sumOfDigits) {
this.file = file;
this.sumOfDigits = sumOfDigits;
}
#Override
public void run() {
sumOfDigits.sum(file);
}
}
The ReentrantLock maintains a count of how many times it has been locked by the current thread. This count is decremented every time you call unlock() and the lock is release when the count reaches zero. Thus, to unlock the lock, you must call unlock() as many times as you have called lock() or tryLock().
In your code, you call tryLock() and if it is successful, you then call lock() inside the try/finally block and then you call unlock() once.
The first thread to lock the ReentrantLock will thus increment the count to two but only decrement the count to one, so the lock is never released. Therefore, no other thread can ever acquire the lock.
You should use tryLock() or lock() to the lock the ReentrantLock, not both.
I have been learning multithreading in Java since recently and I encountered an example in the book. It goes something like this.
class NewThread implements Runnable {
String name;
Thread t;
boolean suspendFlag;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
suspendFlag = false;
t.start();
}
public void run() {
try {
for(int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
synchronized(this) {
while(suspendFlag) {
wait();
}
}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
synchronized void mysuspend() {
suspendFlag = true;
}
synchronized void myresume() {
suspendFlag = false;
notify();
}
}
class Te {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.mysuspend();
System.out.println("Suspending thread One");
Thread.sleep(1000);
ob1.myresume();
System.out.println("Resuming thread One");
ob2.mysuspend();
System.out.println("Suspending thread Two");
Thread.sleep(1000);
ob2.myresume();
System.out.println("Resuming thread Two");
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
try {
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
Now in this example as you can see, there is a resume and a suspend method which gets called a couple of times in the program's main method. But when I remove the synchronized block in the run method, it displays an error something like this.
Exception in thread "Two" java.lang.IllegalMonitorStateException
I acually wanted to know, why do we need the synchronized block for the while statement. Doesn't the while resume when the value of suspendFlag change?
Here's what could happen if there was no synchronization:
Thread A could check suspendFlag and find it to be true,
Thread B could set suspendFlag=false; and then call notify();
Thread A could then call wait() (because suspendFlag was true when it checked.), and now Thread A is hung, waiting for a notification that will never happen.
The synchronization prevents thread B from changing the suspendFlag in between the moment when thread A checked it, and the moment when thread A actually begins to wait for the notification.
I'm learning Thread in java.
The following example shows how to suspend, resume and stop threads:
class MyNewThread implements Runnable {
Thread thrd;
boolean suspended;
boolean stopped;
MyNewThread(String name) {
thrd = new Thread(this, name);
suspended = false;
stopped = false;
thrd.start();
}
public void run() {
System.out.println(thrd.getName() + " starting.");
try {
for(int i = 0; i<1000; i++) {
System.out.print(i + " ");
if(i%10 == 0) {
System.out.println();
Thread.sleep(250);
}
synchronized(this) {
while(suspended) {
wait();
}
if(stopped) break;
}
}
} catch(InterruptedException ex) {
System.out.println(thrd.getName() + " interrupted.");
}
System.out.println(thrd.getName() + " exiting.");
}
synchronized void mystop() {
stopped = true;
suspended = false;
notify();
}
synchronized void mysuspend() {
suspended = true;
}
synchronized void myresume() {
suspended = false;
notify();
}
}
public class Suspend {
public static void main(String[] args) {
MyNewThread ob1 = new MyNewThread("My Thread");
try {
Thread.sleep(1000);
ob1.mysuspend();
System.out.println("Suspending Thread.");
Thread.sleep(1000);
ob1.myresume();
System.out.println("Resuming Thread.");
Thread.sleep(1000);
ob1.mysuspend();
System.out.println("Suspending Thread.");
Thread.sleep(1000);
ob1.myresume();
System.out.println("Resuming Thread.");
Thread.sleep(1000);
ob1.mysuspend();
System.out.println("Stopping Thread.");
ob1.mystop();
} catch(InterruptedException ex) {
System.out.println("Main Thread interrupted.");
}
try {
ob1.thrd.join();
} catch(InterruptedException ex) {
System.out.println("Main Thread interrupted.");
}
System.out.println("Main Thread exiting.");
}
}
But this block:
synchronized(this) {
while(suspended) {
wait();
}
if(stopped) break;
}
Why this block must be specified synchronized?
I know "synchronized" uses to control Threads's access to shared resource and how to use this key word, but in the example, there're only 2 threads: Main thread and ob1 thread. And Main thread does not enter that synchronized block or any synchronized method in MyThread class. I just cant figure out the reason.
I tried to remove the "synchronized" key word precedes the block. the program returned an error in thread "My Thread" while the main thread still finished it's execution.
To answer your direct question: you need to synchronize on this because you are calling wait() on this.
And in order for wait() to be called, the calling thread must own the monitor of the object wait() is called on.
So: you need that synchronized block (or method) to prevent an IllegalMonitorStateException for the following call to wait()!
I am using single thread executor for long-running threads like this:
executor = Executors.newSingleThreadExecutor(THREAD_FACTORY);
executor.submit(new LongRunnable());
which checks a flag to be stopped:
private class LongRunnable implements Runnable {
#Override
public void run() {
while (isRunning.get()) {
try {
doSomething();
} catch (InterruptedException e) {
...
}
}
}
}
and whole execution is interrupted that way:
#Override
public void close() throws Exception {
isRunning.set(false);
executor.shutdownNow();
}
Still I can see some threads not gc-ed in profiler (while by logs, runnable they were executing has quit outermost while loop).
Question: does provided working with threads strategy memory-leak-free and thread-leak-free?
I am not able to see any issue with executor or shutDownNow. Probably you are looking at different threads in your profiler.
Try this program which is similar to the one in your question and you can see the thread is no longer there after successful shutdown.
public class ExecutorShutdownTest {
private static ExecutorService executor;
private static AtomicLong executorThreadId = new AtomicLong(0);
public static void main(String[] args) {
// get thread MX bean
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// create an executor and start the task
executor = Executors.newSingleThreadExecutor(new TestThreadFactory());
LongRunnable runnable = new LongRunnable();
executor.submit(runnable);
// main thread: keep running for sometime
int count = 5;
while (count-- > 0) {
try {
Thread.sleep(1000);
System.out.println(String.valueOf(threadMXBean.getThreadInfo(executorThreadId.longValue())).replace("\r", "").replace(
"\n", ""));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// main thread: stop the task
try {
runnable.close();
System.out.println(String.valueOf(threadMXBean.getThreadInfo(executorThreadId.longValue())).replace("\r", "").replace("\n", ""));
} catch (Exception e) {
e.printStackTrace();
}
// main thread: run some more time to verify the executor thread no longer exists
count = 5;
while (count-- > 0) {
try {
Thread.sleep(1000);
System.out.println(String.valueOf(threadMXBean.getThreadInfo(executorThreadId.longValue())).replace("\r", "").replace("\n", ""));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static class LongRunnable implements Runnable {
private volatile boolean isRunning = true;
#Override
public void run() {
while (isRunning) {
System.out.println("Running");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//ignore
}
}
System.out.println("Stopped");
}
public void close() throws Exception {
System.out.println("Stopping");
isRunning = false;
executor.shutdownNow();
}
}
private static class TestThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
TestThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0) {
#Override protected void finalize() throws Throwable {
super.finalize();
// probably bad idea but lets see if it gets here
System.out.println("Executor thread removed from JVM");
}
};
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
executorThreadId.set(t.getId());
System.out.println("Executor thread created");
return t;
}
}
}
Here's a sample program using the single-thread Executor that manages to strand a thread so that the JVM can't shut down, but it only manages to do it by not calling shutdownNow:
import java.util.concurrent.*;
public class Exec {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(new MyTask());
Thread.sleep(20000L);
// executor.shutdownNow();
int retryCount = 4;
while (!executor.isTerminated() && retryCount > 0) {
System.out.println("waiting for tasks to terminate");
Thread.sleep(500L);
retryCount -= 1;
}
}
}
class MyTask implements Runnable {
public void run() {
int count = 0;
try {
while (!Thread.currentThread().isInterrupted() && count < 10) {
Thread.sleep(1000L);
count += 1;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("all done");
}
}
The thread used by the executor has a separate life cycle from the task, this example shows how the task finishes but the thread goes on. Uncommenting the shutdownNow results in the executor's thread terminating. Otherwise the main thread sleeps for a while and exits, leaving the executor's thread hanging out, preventing the JVM from exiting.
My guess is that your close method isn't getting called and your executor never gets shut down. To get more useful answers please add a MVCE so that we can reproduce the problem.
Consider that with interruption there's no need to keep a reference to the Runnable to set the flag. As I read the question the task not finishing is not an issue here, but it would still be better to make the Runnable respond to interruption and lose the flag, just because having less things to keep track of is always an improvement.
Please show me how to make thread wait. for example wait if i == 0 and go again when i == 1
public class Main {
public Main() {
}
public void method() {
Thread thread = new Thread(new Task());
// I want to make wait it when I want
// for example wait if i == 0 and go again when i = 1
}
public static void main(String[] args) {
new Main();
}
}
This is suitable for a CountDownLatch.
public static void main( String[] args ) throws Exception {
final CountDownLatch latch = new CountDownLatch( 1 );
System.out.println( "Starting main thread" );
new Thread( new Runnable() {
public void run() {
System.out.println( "Starting second thread" );
System.out.println( "Waiting in second thread" );
try {
latch.await();
} catch ( InterruptedException e ) {
e.printStackTrace();
}
System.out.println( "Stopping second thread" );
}
} ).start();
Thread.sleep( 5000 );
System.out.println( "Countdown in main thread" );
latch.countDown();
Thread.sleep( 1000 );
System.out.println( "Stopping main thread" );
}
You might be able to do this with a semaphore
To avoid active waiting try use wait() and notify() or notifyAll() methods. Wait() can make thread stop until someone call notify() or notifyAll() on same object as wait(). One of condition is that thread must be in possession of monitor of object on which will be invoking wait(), notify() or notifyAll().
Here is an example
import java.util.concurrent.TimeUnit;
public class StartPauseDemo extends Thread {
volatile int i = 1;
public void pause() {
i = 0;
}
public synchronized void unPause() {
i = 1;
notify();// wake up thread
}
#Override
public void run() {
while (i==1) {
// logic of method for example printing time every 200 miliseconds
System.out.println(System.currentTimeMillis());
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (i==0) {
synchronized (this) {// thread must possess monitor of object on
// which will be called wait() method,
// in our case current thread object
try {
wait();// wait until someone calls notify() or notifyAll
// on this thred object
// (in our case it is done in unPause() method)
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
// test - pausing and unpausing every 1 sec
public static void main(String[] args) throws InterruptedException {
StartPauseDemo sp = new StartPauseDemo();
sp.start();// start thread
while (true) {
System.out.println("pausing");
sp.pause();
TimeUnit.SECONDS.sleep(1);
System.out.println("unpausing");
sp.unPause();
TimeUnit.SECONDS.sleep(1);
}
}
}
Output:
pausing
unpausing
1338726153307
1338726153507
1338726153709
1338726153909
1338726154109
pausing
unpausing
1338726155307
1338726155507
... and so on
Using such a flag is not necessarily the best approach, but to answer your specific question: you could make your int volatile. See below a simple example that you can run as is - the fact that i is volatile is crucial for this to work.
The output is (it could be different from run to run due to thread interleaving):
i=1
I'm doing something
I'm doing something
i=0
I'm waiting
I'm waiting
i=1
I'm doing something
I'm doing something
I'm doing something
i=0
I'm waiting
I'm waiting
interrupting
I was interrupted: bye bye
public class TestThread {
private static volatile int i = 0;
public static void main(String[] args) throws InterruptedException {
Runnable r = new Runnable() {
#Override
public void run() {
try {
while (true) {
while (i == 1) {
System.out.println("I'm doing something");
Thread.sleep(5);
}
while (i == 0) {
System.out.println("I'm waiting");
Thread.sleep(5);
}
}
} catch (InterruptedException ex) {
System.out.println("I was interrupted: bye bye");
return;
}
}
};
Thread t = new Thread(r);
t.start();
i = 1;
System.out.println("i=1");
Thread.sleep(10);
i = 0;
System.out.println("i=0");
Thread.sleep(10);
i = 1;
System.out.println("i=1");
Thread.sleep(10);
i = 0;
System.out.println("i=0");
Thread.sleep(10);
t.interrupt();
System.out.println("interrupting");
}
}