Java synchronization with callback - java

I am developing a module inside my system where based on some event the user has to receive sms.
I have the following situation
synchronized(notificationPhoneNumber)
{
SmsProvider.sendSms(notificationPhoneNumber, smsText);
}
The code of the method sendSms is running asynchronious:
public static void send(final NotificationPhoneNumber npn, final String smsText)
{
Thread smsSender = new Thread(new Runnable()
{
public void run()
{
//sms sending code runs here....
}
});
smsSender.start();
}
So the question is how long is the notificationPhoneNumber object locked in this case? Is it going to be locked by the time the thread finishes its job or not?

As long as
SmsProvider.sendSms(notificationPhoneNumber, smsText);
doesn't return. That means, your sendsms() method will create a thread and return. Just for that amount of time.
Also, if you start your thread in your method. The created thread will just hold the reference but not the lock after sendsms() returns.
The lock and synchronization are external to sendsms(). Whichever thread calls sendsms()
will acquire the lock and the code within sendsms() has no knowledge of it.

synchronized(notificationPhoneNumber){
...
}
Here NotificationPhoneNumber object will be locked untill synchronized block executed and once it is execution is over, Thread will release the lock of that Object.
A synchronized statement acquires a mutual-exclusion lock (ยง17.1) on
behalf of the executing thread, executes a block, then releases the
lock. While the executing thread owns the lock, no other thread may
acquire the lock.
read more on documentation

Related

Java synchronization: how to have waiting threads not execute the synchronized task

Suppose I have a piece of code in Java that I want to be executed synchronously, however when the thread that owns the lock releases that lock, I do not want waiting threads to execute the synchronized code any more. I just want them to wait until the synchronized code has finished running.
So, when thread 1 enters the synchronized code (method, code block) it must get a lock on that code. Any subsequent threads must then wait for the first thread to finish running the code. So far, regular code synchronization.
However in my case, when the first thread is finished, and releases the lock, I want the waiting threads to skip that synchronized piece of code (the code updates a resource that is used by all threads).
How would I go about creating this in Java using the synchronization features? Currently I am not using the sync features, instead I am using a concurrent collection holding the lock (context), like herebelow. However, the process of locking still needs to be synchronized somehow, because two threads are able to get a lock on the context.
Cheers!
Kjeld
/*
* A concurrently accessible set of contexts.
*/
private static final Set<String> LOCKED_CONTEXTS;
static {
LOCKED_CONTEXTS = ConcurrentHashMap.newKeySet(); // meanwhile, I replaced this with Collections.synchronizedSet(new HashSet<>())
}
...
if (!LOCKED_CONTEXTS.contains(context)) {
LOCKED_CONTEXTS.add(context);
log.debug("Locked context: {}", context);
try {
doTask();
} finally {
LOCKED_CONTEXTS.remove(context);
log.debug("Released context: {}", context);
}
} else {
log.debug("Waiting for context to be released: {}", context);
while (LOCKED_CONTEXTS.contains(context)) {
}
log.debug("The waiting is over, context is released: {}", context);
}
I think you want to combine a lock with a semaphore.
tryLock on the lock
if you got it, do work. At the end of the work, mark the semaphore as complete
if you did not get it, wait for the semaphore to complete
Maybe I don't fully understand your use-case, but from what I get you want a piece of code to only run once for all triggers during its execution, but again if any trigger happens outside of the previous execution window.
Does this cover it?
class Work {
private volatile boolean done;
void queueWorkOnce() {
done = false;
actualWork();
}
private synchronized void actualWork() {
if (!done) {
//TODO: do work
done = true;
}
}
}

What's the inter-thread communication mechanism that can await and release underlying thread resource at the same time

I am looking for an inter-thread communication mechanism that can await and release underlying thread resource at the same time. In my example below, when the executorService is initialized with only 1 thread, the second task will be stuck because the thread is held by t1 even though it's await. The code below will only work if you change to initialize the executorService with 2 threads.
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(1);
CountDownLatch cdl = new CountDownLatch(1);
executorService.submit(() -> {
System.out.println("start t1");
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t1 done");
});
executorService.submit(() -> {
System.out.println("start t2");
cdl.countDown();
System.out.println("t2 done");
});
System.out.println("Master thread ends");
}
The output when executorService is initialized with 1 thread.
start t1
Master thread ends
The output when executorService is initialized with 2 threads.
start t1
Master thread ends
start t2
t2 done
t1 done
Ideally, when t1 is waiting, it doesn't need to hold the underlying thread such that task2 can run within this thread pool. A real-world use case of this problem is that if I have a thread pool, and the tasks will be submitted/scheduled back to the same pool for retries. Theoretically, the process will be stuck when all tasks submitted failed immediately because there are no threads for running the retry tasks.
Creating a separate thread pool for retry can solve this problem, but I am wondering if JAVA provides an inter-thread communication mechanism that allows waiting and releasing the underlying thread at the same time, so that only 1 thread pool is needed.
The only way to release underlying thread resource is to completely return from the main method of the task (usually Runnable::run). To await at the same time, the event producer should be subscribed in asynchronous way. Not every producer has asynchronous interface. CompletbleFuture has (method whenComplete), but CountDownLatch has not. However, you can extend CountDownLatch with asynchronous finctionality, subscribe to its completion, return from run() and wait. I did so in my DF4J library: AsyncCountDownLatch.java

Java - Threads state when performing I/O operations

Suppose a Java thread performs some I/O operation like reading a file with traditional blocking Java I/O.
The question is: What is the state of the thread while waiting?
I don't know if it is RUNNING (doing some active wait) or WAITING (maybe there is some kind of monitor that wakes up the thread when file data is ready).
How can I find it out?
Thanks.
A thread that is blocked in an I/O syscall should be in RUNNABLE state, according to my reading of the javadocs.
public static final Thread.State RUNNABLE
Thread state for a runnable thread. A thread in the runnable state is executing in the Java virtual machine but it may be waiting for other resources from the operating system such as processor.
The other possible thread states are far more tightly specified, and the respective specifications make them clearly inapplicable.
I have confirmed this by testing (with OpenJDK Java 8 on Linux).
public class Test {
public static void main(String[] args) throws Exception {
Thread t = new Thread(new Runnable() {
public void run() {
try {
while (true) {
System.in.read(); // Block for input
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.start();
while (true) {
System.out.println("State: " + t.getState());
Thread.sleep(1000);
}
}
}
Now, hypothetically, if you designed your application so that one thread handed off I/O requests to second thread, then the first thread would be in WAITING (or possibly BLOCKED) state waiting for the I/O thread to deliver. However, normal Java I/O doesn't behave like that. The thread requesting I/O is the one that makes the syscall.
How can I find it out?
Write tests; see above.
Deep-dive the OpenJDK source code.
You can find the status of thread using Thread.getState(). It will return
java.lang.Thread.State

Release resource on shutdown

I have a spring-boot app in which I use ScheduledExecutorService to create single threaded executor. In this single thread, I process database records. I acquire lock on many records to process them and want to release the lock as soon as JVM is shutdown. I have tried to register a JVM shutdown hook.
// Create single threaded
ScheduledExecutorService executor;= Executors.newSingleThreadScheduledExecutor();
executor.scheduleWithFixedDelay(dbRecordProcessor, 1000, delay, TimeUnit.MILLISECONDS);
// Registering shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
logger.info("Executing shutdown hook.....");
executor.shutdown();
}
});
//
DbRecordProcessor implements Runnable {
public void run() {
try {
// get all the records from DB by acquiring lock
}catch(Exception e) {
}finally {
// Release the lock on record
}
// Acquire lock on records
// loop on them
// Process them
// Release the lock after processing
}
}
All I want is, When JVM shutdown hook is invoked, all the records on which lock was acquired must be released. I can not blindly say to "unlock" on all the records because some of the records might be locked by another instance SO I want to unlock only those records which are locked by this running instance.
I wanted to know just by calling "executor.shutdown()", It would release the lock from all the records? Please help me.
It seems to me what you are trying to achieve should be done with a transaction. Process data in batches of say 100 records not to make transaction too big, then when executor is shut down transaction will be rolled back and all the record level db locks will be released.
shutdown() method will interrupt all idle worker and you can put cleanup code on interrupt handle or in finally block.It is always advisable to do clean up .If you call shutdownNow() .It will interrupt all worker threads.

Execute code in the same method after Thread.join() executes

I have the problem, that the join Method, to kill a thread, is not executing the rest of the method, which was started also in the thread. Here is a code example:
private static Thread thread;
public static void addMessage(final String s) {
thread = new Thread() {
#Override
public void run() {
String data = Message.send(s);
addMessageToContainer(data);
}
};
thread.start();
}
public static void addMessageToContainer(String data) {
//Do some stuff with the data
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
//This code here will not be executed.
}
So normally, of course I can execute the code before I call the join function. But I have to load after this thread execution a webview with some content. So when I do remove the join, it will give me the following error message:
java.lang.RuntimeException: java.lang.Throwable: A WebView method was called on thread 'Thread-9072'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {5ac9b39} called on null, FYI main Looper is Looper (main, tid 1) {5ac9b39})
So what can I do to load the content after the thread has executed?
Join doesn't kill a thread. Join waits until that thread kills itself. So that code would be executed- just at some time in the future, when that thread decides its done. Calling wait on a thread from that thread will cause it to deadlock and never do anything, yet never die. So in the case above where you're calling it from the thread itself, it will just hang forever.
There is no way to kill a thread directly, because its impossible to do so safely. The way to kill a thread from the outside is to interrupt it, and let the thread check if it isInterrupted() every so often and if so kill itself. The way to kill a thread from the inside is to return from the runnable's run method.
Your webview error is totally unrelated. You can only touch views on the main thread. Don't do anything with a webview on a thread.

Categories

Resources