Thread not awake when timed wait elapsed in java - java

I am study wait(long timeout) in java,and in the offcial document I found below description:
Some other thread invokes the notify method for this object and thread T happens to be arbitrarily chosen as the thread to be awakened.
Some other thread invokes the notifyAll method for this object.
Some other thread interrupts thread T.
The specified amount of real time has elapsed, more or less. If timeout is zero, however, then real time is not taken into consideration and the thread simply waits until notified.
The last item said The specified amount of real time has elapsed, more or less,so in my option if we invoke wait(time),when time elapsed,the thread should awake itself.
So I wrote below code for test.
public static void testTimedWait() {
Object lock = new Object();
DateTimeFormatter df = DateTimeFormatter.ofPattern("HH:mm:ss:SSS");
new Thread(() -> {
synchronized (lock) {
try {
System.out.println(LocalTime.now().format(df) + "\t" + Thread.currentThread().getName() + " start to run");
lock.wait(5_000);
System.out.println(LocalTime.now().format(df) + "\t" + Thread.currentThread().getName() + " finished running");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}, "thread-1").start();
new Thread(() -> {
synchronized (lock) {
try {
System.out.println(LocalTime.now().format(df) + "\t" + Thread.currentThread().getName() + " start to run");
Thread.sleep(10_000);
//lock.notifyAll();
System.out.println(LocalTime.now().format(df) + "\t" + Thread.currentThread().getName() + " finished running");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}, "thread-2").start();
}
In Thread-1 I invoke lock.wait(5_000) and in Thread-2 I invoke Thread.sleep(10_000),so once the code start to run,Thread-1 should awake after 5 seconds and Thread-2 should awake after 10 seconds theoretically.
When we run code above,the result listed like below:
Thread-1 doesn't awake after 5 seconds!
Could someone help to understand why thread not awake when the wait time has elasped,thanks in advance!
Update1:
Change code as below:
public static void testTimedWait() {
Object lock = new Object();
DateTimeFormatter df = DateTimeFormatter.ofPattern("HH:mm:ss:SSS");
new Thread(() -> {
synchronized (lock) {
try {
System.out.println(LocalTime.now().format(df) + "\t" + Thread.currentThread().getName() + " start to run");
lock.wait(20_000);
System.out.println(LocalTime.now().format(df) + "\t" + Thread.currentThread().getName() + " finished running");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}, "thread-1").start();
new Thread(() -> {
synchronized (lock) {
try {
System.out.println(LocalTime.now().format(df) + "\t" + Thread.currentThread().getName() + " start to run");
Thread.sleep(10_000);
//lock.notifyAll();
System.out.println(LocalTime.now().format(df) + "\t" + Thread.currentThread().getName() + " finished running");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}, "thread-2").start();
}
Above code make Thread-1 wait for 20 seconds and Thread-2 sleep for 10 seconds,Thread-1 will awake after the specific seconds.Now it works as expected.
Update2:
Remove Thread-2
public static void testTimedWait() {
Object lock = new Object();
DateTimeFormatter df = DateTimeFormatter.ofPattern("HH:mm:ss:SSS");
new Thread(() -> {
synchronized (lock) {
try {
System.out.println(LocalTime.now().format(df) + "\t" + Thread.currentThread().getName() + " start to run");
lock.wait(20_000);
System.out.println(LocalTime.now().format(df) + "\t" + Thread.currentThread().getName() + " finished running");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}, "thread-1").start();
}
The test result is also working as expected.But I still do not know why Thread-1 not awake when it wait longer then Thread-2

Your threads are both synchronized on the same object. Therefore, you have to pay attention to the methods’s effect on synchronization:
Object.wait(…):
“This method causes the current thread (referred to here as T) to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object.”
…
“The thread T is then removed from the wait set for this object and re-enabled for thread scheduling. It competes in the usual manner with other threads for the right to synchronize on the object; once it has regained control of the object, all its synchronization claims on the object are restored to the status quo ante - that is, to the situation as of the time that the wait method was invoked.”
Thread.sleep(long): “The thread does not lose ownership of any monitors.”
So, when the first thread invokes wait, it releases the lock, which is the only way how the second thread could even enter the synchronized block. Then, the second thread calls sleep, which does not release the lock. Therefore, after the time has elapsed, the first thread can not proceed, as it can’t acquire the lock, the second thread is still holding.
Of course, if you extend the first thread’s waiting time, to wait longer than the second thread, the lock has been released in the meanwhile and the first thread can proceed immediately after the waiting time.

Related

Parallel stream doesn't look like working in parallel, completely

1. Set's parallelStream doesn't use enough thread.
Java8 parallelStream doesn't working exactly parallel.
In my computer, java8 set's parallelStream is not using enough thread when task's count is smaller than processor's count.
public class ParallelStreamSplitTest {
#Test
public void setStreamParallelTest() {
System.out.printf("Total processor count : %d \n", Runtime.getRuntime().availableProcessors());
long start = System.currentTimeMillis();
IntStream.range(1, 8).boxed().collect(Collectors.toCollection(HashSet::new)).parallelStream().forEach((index) -> {
System.out.println("Starting " + Thread.currentThread().getName() + ", index=" + index + ", " + new Date());
try {
Thread.sleep(1000);
} catch (Exception e) {
}
});
long end = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() + "'s elapsed time : " + (end - start));
}
#Test
public void intStreamParallelTest() {
System.out.printf("Total processor count : %d \n", Runtime.getRuntime().availableProcessors());
long start = System.currentTimeMillis();
IntStream.range(1, 8).parallel().forEach(index -> {
System.out.println("Starting " + Thread.currentThread().getName() + ", index=" + index + ", " + new Date());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
});
long end = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() + "'s elapsed time : " + (end - start));
}
}
In my code, setStreamParallelTest takes 4 seconds whereas intStreamParallelTest takes 1 second.
I expect that setStreamParallelTest also done in 1 seconds.
Is it bug?
2. Is it okay to use parallel stream to call another api in web application? If it is wrong, why?
My web application need to call another api server in parallel. So I use parallel stream to call api.
Sets.newHashSet(api1, api2, api3, api4).parallelStream().forEach(api -> callApiSync(api))
I think all requests bound for my server share a fork-join pool. so, It looks dangerous when one of api's response is slow.
Is it correct?
The contract for parallelStream says:
Returns a possibly parallel Stream with this collection as its source. It is allowable for this method to return a sequential stream.
If you want to invoke several tasks in parallel, use an ExecutorService.

Rxjava2 blockingSubscribe vs subscribe

I have read the explanation about blockingSubscribe() and subscribe() but neither I can write nor find an example to see the difference of these. It seems that both of these work the same way. Could someone provide an example of these 2, preferably in Java.
blockingSubscribe blocks the current thread and processes the incomnig events on there. You can see this by running some async source:
System.out.println("Before blockingSubscribe");
System.out.println("Before Thread: " + Thread.currentThread());
Observable.interval(1, TimeUnit.SECONDS)
.take(5)
.blockingSubscribe(t -> {
System.out.println("Thread: " + Thread.currentThread());
System.out.println("Value: " + t);
});
System.out.println("After blockingSubscribe");
System.out.println("After Thread: " + Thread.currentThread());
subscribe gives no such confinement and may run on arbitrary threads:
System.out.println("Before subscribe");
System.out.println("Before Thread: " + Thread.currentThread());
Observable.timer(1, TimeUnit.SECONDS, Schedulers.io())
.concatWith(Observable.timer(1, TimeUnit.SECONDS, Schedulers.single()))
.subscribe(t -> {
System.out.println("Thread: " + Thread.currentThread());
System.out.println("Value: " + t);
});
System.out.println("After subscribe");
System.out.println("After Thread: " + Thread.currentThread());
// RxJava uses daemon threads, without this, the app would quit immediately
Thread.sleep(3000);
System.out.println("Done");

Parallel Execution: How to update Excel WorkBook using Synchronized method, only after synchronized method execution is completed?

I have written a non-static synchronized method in a class to avoid multiple threads updating the Excel Workbook at the same time. For example Thread with ID #9 and #10 are trying to update Excel, expected is that Thread#9 should complete the operation of synchronized method and then Thread#10 should be able to invoke the method which is not happening for us. Below is the code snippet.
public synchronized boolean put(String parameterName, String parameterValue) {
try {
System.out.println("Start Time:= " + Thread.currentThread().getId() + " :: " + LocalDateTime.now().toString());
updateData(data.get("XLFileName"), data.get("XLSheetName"), parameterName, parameterValue, data.get("TestCaseID"), data.get("Iteration"));
System.out.println("End Time:= " + Thread.currentThread().getId() + " :: " + LocalDateTime.now().toString());
return true;
} catch (FilloException flex) {
flex.printStackTrace();
// extentTest.log(LogStatus.FATAL, "A", flex.getMessage());
return false;
}
}
public void updateData(String XLFileName, String XLSheet, String parameterName, String parameterValue, String testCaseID, String iteration) throws FilloException {
Fillo fillo = new Fillo();
Connection connection = fillo.getConnection(XLFileName);
String strQuery = "Update " + XLSheet + " Set " + parameterName + "='" + parameterValue + "' where TestCaseID = '" + testCaseID + "' and Iteration = '" + iteration + "'";
connection.executeUpdate(strQuery);
connection.close();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Current Output:
Start Time:= 10 :: 2017-03-20T15:03:31.041
1 row(s) affected
Start Time:= 9 :: 2017-03-20T15:03:31.619
1 row(s) affected
End Time:= 10 :: 2017-03-20T15:03:41.201
End Time:= 9 :: 2017-03-20T15:03:41.675
Expected Output:
Start Time:= 10 :: 2017-03-20T15:03:31.041
1 row(s) affected
End Time:= 10 :: 2017-03-20T15:03:41.201
Start Time:= 9 :: 2017-03-20T15:03:31.619
1 row(s) affected
End Time:= 9 :: 2017-03-20T15:03:41.675
Tried with synchronized block as well.
Can you try with Synchronized block with lock on class as shown below.
public synchronized boolean put(String parameterName, String parameterValue) {
synchronized (DataBook.class) {
try {
System.out.println("Start Time:= " + Thread.currentThread().getId() + " :: " + LocalDateTime.now().toString());
updateData(data.get("XLFileName"), data.get("XLSheetName"), parameterName, parameterValue, data.get("TestCaseID"), data.get("Iteration"));
System.out.println("End Time:= " + Thread.currentThread().getId() + " :: " + LocalDateTime.now().toString());
return true;
} catch (FilloException flex) {
flex.printStackTrace();
return false;
}
}
}
Since this is not static, the lock used here is an intrinsic lock, i.e. a lock per object. What it means is that you have a lock per thread, so each thread has the right to execute its own put method, thus the output you observe.
What I would suggest to obtain the desired output is to make this method static, so that the lock is associated to the class, and only one Thread will be able to access it at a time, giving you the expected output (or almost, thread 9 could start sooner than Thread 10):
public static synchronized boolean put(String parameterName, String parameterValue)

Pause execution of a loop in main method till all Threads finish Java 1.5

I am reading multiple arguments from command line using Java 1.5 . The arguments are names of flat files. I loop thru the arguments in the main method and call a method which in turn creates a bunch of threads to process the file. I need to pause the loop till all threads processing the first argument complete and then move on to create threads for the second argument. How can I queue the arguments or pause the loop execution in my main method till all threads processing current argument complete?
Use Threadpools and an Executor. Take a look at the java.util.concurrent package.
for(String argument:args){
//you said you want multiple threads to work on a single argument.
//create callables instead and use a ThreadPool
List<Callable<YourResult>> lstCallables = createCallablesFor(argument);
List<Future<YourResult>> futures = Executors.newCachedThreadPool().invokeAll(lstCallables);
for(Future<YourResult> future:futures){
//this get() waits until the thread behind the current future is done.
// it also returns whatever your callable might return.
future.get();
}
// at this point, all the threads working on the current argument are finished
// and the next loop iteration works on the next argument
}
I wonder if you are looking for something like cyclic barriers.
You need to start the thread job inside the loop for one argument so that after one job is finished next loop is started and next thread job for next argument is started. And further you can work in your thread job where you defined that.
Example: this is just a snippet
for (int i = 0; i < count; i++) {
t[i] = new RunDemo();
String[] serverList = srv[i].split(",");
String logName = filename + "_" + serverList[0] + "_log";
String sql = "INSERT INTO .....(any query)";
t[i].setStr("sqlplus -L " + username[i] + "/" + password[i] + "#"
+ serverList[1] + ":" + serverList[2] + "/" + serverList[3]
+ " #" + filename1);
t[i].setLogName(logName);
t[i].setDirectory(dir);
try{
conn.UpdateQuery(sql);
log.info("Inserted into the table data with query " + sql);
}
catch (Exception e){
log.info("The data can't be inserted into table with " + e.getMessage() + " sql query " + sql);
}
new Thread(t[i]).start();
}
Here in every loop new thread with different serverList is created and started.
Now the job definition is given below:
public void run() {
JShell jshell = new JShell();
try {
log.info("Command is: " + this.str + " log name: " + this.LogName + " in directory: " + this.directory);
jshell.executeCommand(this.str, this.LogName, this.directory);
log.info("Executed command successfully");
} catch (Exception e1) {
log.info("Error at executing command with error stack: ");
e1.printStackTrace();
}
DBConnection conn1 = new DBConnection();
String sql = "UPDATE patcheventlog SET ENDTIME=SYSDATE WHERE LOGFILE='" + this.directory + this.LogName + "'";
try {
//conn1.callConnection("192.168.8.81", "d2he");
conn1.callConnection(ip, sid);
conn1.UpdateQuery(sql);
conn1.disposeConnection();
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.print(this.LogName);
}
So this is how you work with the threads inside the loop. You don't need to pause your loop.
Hope that helps.

java multithreaded application: getting thread blocked time

I am calling threadInfo.getBlockedCount() and getBlockedTime() just before the worker threads die.
I get a blocked count of 1, but a blocked time of 0.
Does this mean that the thread was blocked but it the blocked time was less than a millisecond?
If the above is true, is there another way to get accurate time for which a thread was blocked?
However, the blocked time of a thread (being blocked) only seems to return a non-zero result if the ThreadMXBean#setThreadContentionMonitoringEnabled(true) is called * before * starting the thread. Otherwise, it'd always return zero (or -1 if the contention monitoring is disabled). The code below demos this:
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
public class BlockedTimeMain {
public static void main(String[] _) throws InterruptedException {
ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
final Object lock = new Object();
Thread t = new Thread("Foo") {
#Override public void run() {
// This will block forever
synchronized(lock) {
// Will never get here
System.out.println("Got the lock from " + Thread.currentThread());
}
}
};
synchronized(lock) {
t.start();
mbean.setThreadContentionMonitoringEnabled(true);
for (int i=0; i < 5; i++) {
ThreadInfo[] tis = mbean.getThreadInfo(new long[]{t.getId()}, true, true);
ThreadInfo ti = tis[0];
if (ti.getThreadId() != t.getId())
throw new AssertionError("Unexpected " + t.getId() + " vs " + tis[0].getThreadId());
System.out.println(t + " " + ti.getThreadState()
+ ": blockedTime=" + ti.getBlockedTime() + "/" + ti.getBlockedCount()
+ ", waitTime" + ti.getWaitedTime() + "/" + ti.getWaitedCount());
Thread.sleep(1000);
}
}
System.exit(0);
}
}
Sample Output:
Thread[Foo,5,main] BLOCKED: blockedTime=0/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=0/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=0/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=0/1, waitTime0/0
Can test it out, with something like:
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
public class BlockedTimeMain {
public static void main(String[] _) throws InterruptedException {
ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
mbean.setThreadContentionMonitoringEnabled(true);
final Object lock = new Object();
Thread t = new Thread("Foo") {
#Override public void run() {
// This will block forever
synchronized(lock) {
// Will never get here
System.out.println("Got the lock from " + Thread.currentThread());
}
}
};
synchronized(lock) {
t.start();
for (;;) {
ThreadInfo[] tis = mbean.getThreadInfo(new long[]{t.getId()}, true, true);
ThreadInfo ti = tis[0];
if (ti.getThreadId() != t.getId())
throw new AssertionError("Unexpected " + t.getId() + " vs " + tis[0].getThreadId());
System.out.println(t + " " + ti.getThreadState()
+ ": blockedTime=" + ti.getBlockedTime() + "/" + ti.getBlockedCount()
+ ", waitTime" + ti.getWaitedTime() + "/" + ti.getWaitedCount());
Thread.sleep(1000);
}
}
}
}
Sample Output:
Thread[Foo,5,main] BLOCKED: blockedTime=2/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=1007/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=2012/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=3016/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=4021/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=5025/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=6028/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=7032/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=8035/1, waitTime0/0
Yes it does mean that it was blocked for 0 milliseconds. i.e there was no blocking involved. The thread did not wait for the monitor lock to enter the synchronized block/method.
You are seeing this because you must have written a simple program with one or two threads, and there is no latency.
You will need to induce really heavy load on the threads to actually see positive values.
Apparently, that is what it means, and apparently there isn't a way to get the time to a greater precision. (The javadocs say that the blocked time may be measured and (presumably) accumulated with greater precision, but the ThreadInfo API doesn't expose this information, and there doesn't appear to be any other kosher way to get it.)
I say "apparently", because the javadoc actually describes the time values as "the approximate accumulated elapsed time". This leaves open the possibility that this could be a very rough approximation, possibly with the same granularity as the clock values returned by System.getCurrentTimeMillis(). Also, it doesn't say if accumulated times measured with a high precision timer would be rounded or truncated when converted to millisecond values; i.e. whether zero means "less than 1 millisecond" or "less than 0.5 milliseconds".

Categories