Why this flux isn't executed in single thread? - java

I have my function executed this way:
#EventListener(classes = {ApplicationReadyEvent.class})
public void executeSendingNotificationToServer() {
serverNotificationService.trySendNotification(msgCount, msgTime)
.delaySubscription(Duration.ofMillis(notificationServerProperties.getExecutorDelay()))
.repeat()
.subscribeOn(Schedulers.single())
.subscribe();
}
method trySendNotification is executed somehow(it doesn't matter).
Why its not executed in single thread? I explicitly set Schedulers.single()
And the documentation states that it would be executed in one thread.
Instead I can observe that multiple threads are created(I put thread names logging in method and it prints different names)

You should move the subscribeOn before the delay.
Here is an example, using your code but printing the thread number:
Mono.fromCallable(() -> {
System.out.println("Thread = " + Thread.currentThread().getId());
return "hello world";
})
.delaySubscription(Duration.ofMillis(500))
.repeat()
.subscribeOn(Schedulers.single())
.subscribe();
The output, as you said, shows that it is executed in different threads:
Thread = 14
Thread = 15
Thread = 16
Thread = 17
Thread = 18
Thread = 19
Thread = 20
Thread = 21
Thread = 14
Now, if I move it before like this:
Mono.fromCallable(() -> {
System.out.println("Thread = " + Thread.currentThread().getId());
return "hello world";
})
.subscribeOn(Schedulers.single()) // <- BEFORE
.delaySubscription(Duration.ofMillis(500))
.repeat()
.subscribe();
The output becomes:
Thread = 14
Thread = 14
Thread = 14
Thread = 14
Thread = 14
Thread = 14
Thread = 14
Thread = 14
Thread = 14

Related

Start execution if it is not in progress yet, otherwise wait for the existing execution to finish in concurrent Java method call

Imagine I have a class whose method (process) can be called concurrently.
This method does some processing (doProcess) that cannot be executed concurrently. Moreover, if process method was called, but processing (doProcess) is already in progress - invocation of process should wait until the already started processing (doProcess) is finished and then return (without starting new processing - doProcess). Calling process method will only do actual processing (doProcess) if none of threads is doing actual processing (doProcess) yet.
// Just imaginary example to illustrate the idea
class MyResource() {
val lock = MyLock()
fun process() {
if (!lock.isLocked) {
lock.lock()
doProcess()
lock.unlock()
}
lock.awaitUnlocked()
}
private fun doProcess() {
// actual processing
}
}
What would be the intended concurrency (java.util.concurrent) primitive for the concurrency problem described in the imaginary example above? I thought about ReentrantLock but it does not offer awaitUnlocked. And the java.util.concurrent.locks.Condition seems too low-level for this simple use case.
Sounds like what you are after could be accomplished with a ConcurrentMap - more specifically, computeIfAbsent.
For instance, you can run the code below. Works a bit like a cache - if you what you want is available, simply return it. Otherwise wait for which ever thread gets there first to compute it first.
import java.time.Instant;
import java.util.concurrent.*;
public class ConcurrencyTest
{
private final ConcurrentMap<String, String> processItems = new ConcurrentHashMap<>();
public String process()
{
return processItems.computeIfAbsent("doProcess", k -> doProcess());
}
private String doProcess()
{
try
{
System.out.println(Instant.now() + " -> doProcess() Starting some work on " + Thread.currentThread());
Thread.sleep(100);
System.out.println(Instant.now() + " -> doProcess() Finished some work on " + Thread.currentThread());
return Instant.now().toString();
}
catch(Exception e)
{
throw new RuntimeException("Unexpected Exception : " + e, e);
}
}
/**
* And to test it out.
*
* #param args
* #throws Exception
*/
public static void main(String... args) throws Exception
{
final int THREADS = 10;
final ConcurrencyTest test = new ConcurrencyTest();
final ExecutorService execs = Executors.newFixedThreadPool(THREADS);
final CountDownLatch startingGun = new CountDownLatch(1);
for (int i = 0; i < THREADS; i++)
{
execs.submit(() -> {
System.out.println(Instant.now() + " -> Thread -> " + Thread.currentThread() + " - Awaiting Starting Gun");
try
{
startingGun.await();
}
catch (InterruptedException e)
{
throw new RuntimeException("Failure waiting for the starting gun.");
}
System.out.println(Instant.now() + " -> Running Thread -> " + Thread.currentThread());
String val = test.process();
System.out.println(Instant.now() + " -> Got back " + val + " -> " + Thread.currentThread());
});
}
System.out.println("All tasks submitted.. waiting for 5 seconds then firing the starting gun. ");
Thread.sleep(5_000);
startingGun.countDown();
execs.shutdown();
}
}
Gets me the output below. As you can see only one thread end up executing the code in question. The rest wait on it.
All tasks submitted.. waiting for 5 seconds then firing the starting gun.
2021-12-30T17:59:51.696626Z -> Thread -> Thread[pool-1-thread-3,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696606Z -> Thread -> Thread[pool-1-thread-8,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696245Z -> Thread -> Thread[pool-1-thread-10,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696231Z -> Thread -> Thread[pool-1-thread-6,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696627Z -> Thread -> Thread[pool-1-thread-5,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696633Z -> Thread -> Thread[pool-1-thread-4,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696274Z -> Thread -> Thread[pool-1-thread-2,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696231Z -> Thread -> Thread[pool-1-thread-1,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696620Z -> Thread -> Thread[pool-1-thread-7,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696261Z -> Thread -> Thread[pool-1-thread-9,5,main] - Awaiting Starting Gun
2021-12-30T17:59:56.695927Z -> Running Thread -> Thread[pool-1-thread-5,5,main]
2021-12-30T17:59:56.696031Z -> Running Thread -> Thread[pool-1-thread-6,5,main]
2021-12-30T17:59:56.695968Z -> Running Thread -> Thread[pool-1-thread-4,5,main]
2021-12-30T17:59:56.695863Z -> Running Thread -> Thread[pool-1-thread-10,5,main]
2021-12-30T17:59:56.695832Z -> Running Thread -> Thread[pool-1-thread-8,5,main]
2021-12-30T17:59:56.696063Z -> Running Thread -> Thread[pool-1-thread-2,5,main]
2021-12-30T17:59:56.696133Z -> Running Thread -> Thread[pool-1-thread-3,5,main]
2021-12-30T17:59:56.696254Z -> Running Thread -> Thread[pool-1-thread-9,5,main]
2021-12-30T17:59:56.696230Z -> Running Thread -> Thread[pool-1-thread-7,5,main]
2021-12-30T17:59:56.696204Z -> Running Thread -> Thread[pool-1-thread-1,5,main]
2021-12-30T17:59:56.714154Z -> doProcess() Starting some work on Thread[pool-1-thread-4,5,main]
2021-12-30T17:59:56.814608Z -> doProcess() Finished some work on Thread[pool-1-thread-4,5,main]
2021-12-30T17:59:56.815375Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-5,5,main]
2021-12-30T17:59:56.815422Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-7,5,main]
2021-12-30T17:59:56.815104Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-8,5,main]
2021-12-30T17:59:56.815065Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-3,5,main]
2021-12-30T17:59:56.815093Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-2,5,main]
2021-12-30T17:59:56.815054Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-4,5,main]
2021-12-30T17:59:56.815420Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-6,5,main]
2021-12-30T17:59:56.815387Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-1,5,main]
2021-12-30T17:59:56.815077Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-9,5,main]
2021-12-30T17:59:56.815435Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-10,5,main]

"Run"ing vs. Single stepping in Java Eclipse -

I am trying to update a large (~150,000 line) Java/Eclipse program from 2009 that has several threads, and communicates with a TCP-IP telescope. I wrote new code to do the communications, and that all works fine when separately tested. This is on a Mac - the original worked on Mac OSX 10.6 and nothing later - I'm writing this for current Mac OS 12.xx
In the overall program, there is a thread that receives mouse clicks from the GUI and initiates operation of a thread with runs the communications code. The communications thread stays alive, using parameters passed to it to determine which communication function to execute.
Here's some of the code:
class ActualTask {
ActualTask () {
// PRAA Dec 7 2021
System.out.println("What thread are we in? it's: "+ Thread.currentThread().getName());
while (true) // this is true so we can keep reusing this task!
{
// PRAA Dec 7 2021
//System.out.println("What thread are we in? it's: "+ Thread.currentThread().getName());
if (running)
{
// PRAA Dec 7 2021
System.out.println("Just before call to run() - What thread are we in? it's: "+ Thread.currentThread().getName());
run();
// PRAA Dec 7 2021
System.out.println("What thread are we in? it's: "+ Thread.currentThread().getName());
running = false;
}
}
}
// ------------------------------------
void run()
{
done = false;
successful = true;
telescopeException = null;
// PRAA Dec 7 2021
System.out.println("In run() - thread is: "+ Thread.currentThread().getName());
try
{ // *** execute the telescope task ***
TelescopeGlobals.telescopeProgressTaskData.setBackgroundColor(Color.red); // red when active
telescopeTask.execute();
done = true;
TelescopeGlobals.telescopeProgressTaskData.setBackgroundColor(Color.white); // white when NOT active
}
catch (TelescopeException te)
{
// Clear progress bar before throwing up dialog
TelescopeGlobals.telescopeProgressTaskData.setBackgroundColor(Color.white); // white when NOT active
TelescopeGlobals.telescopeProgressTaskData.clear();
done = true;
successful = false;
telescopeException = te;
Reporting.selctiveAlert(te.getMessage() + "\n" + te.getWhereExceptionOccured());
TelescopeGlobals.telescopeProgressTaskData.setText1("Error: " + te.getMessage());
TelescopeGlobals.telescopeProgressTaskData.setText2("Where: " + te.getWhereExceptionOccured());
}
done = true;
}
}
When I am in "debug" mode, and I single-step through the communications code, things usually execute properly - however, when I hit "Run", things don't go so well -
the first call works ok
the second call appears to do nothing - that is, it doesn't seem to be executing, and none of my print statements print
subsequent calls only print an error message saying the previous task has not completed.
So I'm wondering - what is the difference between the "run" and "debug" modes - why would one work and the other behave differently - and
Does all of the "SwingWorker" stuff from 2009 still work?
Should creating the communications thread be done differently? It is just created once, as shown in the code snippet below:
// Static member above of HighLevelTaskWorker makes sure that one command is dispatched to the telescope at a time.
class HighLevelTaskWorker { // SwingWorker wrapper class
private lib.SwingWorker worker = null;
private boolean done;
private boolean successful;
private TelescopeException telescopeException;
private boolean running;
private TelescopeTask telescopeTask;
public HighLevelTaskWorker()
{
}
public void start(TelescopeTask telescopeTask) {
this.telescopeTask = telescopeTask;
// PRAA Dec 7 2021
System.out.println("What thread are we in? it's: "+ Thread.currentThread().getName());
done = false;
successful = false;
telescopeException = null;
running = true;
if (worker == null) // no need to create this tread over and over again, think of all that Garbage Collecting and tread creation!
{
worker = new lib.SwingWorker() {
public Object construct() {
return new ActualTask();
}
};
worker.start();
}
}
Thanks so much for any help !!!

Scala Process never end when applying Future and ThreadPools for Multi-threading

Here's the code snippet:
object Test {
def main(args: Array[String]): Unit = {
// MARK: parallelization
val pool = Executors.newFixedThreadPool(3)
implicit val xc = ExecutionContext.fromExecutorService(pool)
var taskQueue = new ArrayBuffer[Future[Unit]]()
for (i <- 0 until 10) {
try {
taskQueue += Future {
print(s"in_${i}\n")
Thread.sleep(1000)
}
} catch {
case t: Throwable => {
print(t)
}
}
}
val importTasks = Future.sequence(taskQueue)
importTasks.onSuccess { case res => print("finishOnSuccess") }
Await.result(importTasks, Duration.Inf)
}
}
it will hang forever after all jobs are executed with the following output:
in_1
in_2
in_0
in_4
in_3
in_5
in_8
in_6
in_7
in_9
finishOnSuccess
I tried to call System.exit(0) at the end of main method but still no use. Any suggestions? Thanks!
You need to shutdown ExecutorService of pool by pool.shutdown() after Await. Since the newFixedThreadPool is creating non-daemon thread by defaultThreadFactory.
and this Post explain more about Daemon thread and Non-Daemon thread:
What is Daemon thread in Java?

Java Synchronized : Wired behavior under two threads [duplicate]

This question already has answers here:
If I synchronized two methods on the same class, can they run simultaneously?
(12 answers)
Closed 5 years ago.
I have created a simple Worker :
public class Worker {
public synchronized void writeData() {
try {
System.out.println("write Data , thread id = " + Thread.currentThread().getId());
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void readData() {
try {
System.out.println("readData , thread id = " + Thread.currentThread().getId());
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
AFAIK, If multiple thread access the same Worker instance, the synchronized only blocks threads that access the same method. AKA if thread A invokes writeData and B uses readData, they will not influence each other (Correct me if I am wrong).
BUT, when I tried to demo it by the code below:
private static void testWithThreads() {
final Worker worker = new Worker();
new Thread(() -> {
System.out.println("start read thread");
for (int i = 0; i < 20; i++) {
worker.readData();
}
}).start();
new Thread(() -> {
System.out.println("start write thread");
for (int i = 0; i < 20; i++) {
worker.writeData();
}
}).start();
}
I got the output like this (Note that we have Thread.sleep for 2 seconds here):
start read thread
readData , thread id = 10
start write thread
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
Can anyone explain this to me? It seems they blocked each other in some way.
the synchronized only blocks threads that access the same method
Wrong. It blocks threads trying to synchronize on the same object.
How it works is if A is using writeData for a Worker instance then B cannot use readData or writeData from the same Worker until it is given a chance.
If you were hoping to have your output to be:
read
write
read
write
etc...
then I would suggest using the functions wait(); and notifyAll();
This way you can make thread A give Thread B a turn once it is finished and vice versa.
You can read more about wait() and notifyAll()
here.
synchronized on a method level synchronizes access to all synchronized methods of the Object the methods belongs to, that only one thread can execute in any synchronized method of that object. The other threads will wait even if they try to access other synchronized method than the first thread.
The other Threads will block till the first one will get out from the synchronized blocks.
In your code beetween the invocation of synchornized methods in for loops, there is tiny time slot in which other thread can get into the writeData() before the first get again into readData() - a typical for loop is not atomic operation - but this time slot is so tiny, that it rarely happens - so your output looks like they are blocking each other in some way - and in one point the wind changes and other thread takes the lead.
to be more specific, comments are pointing where "unsynchronized" time slot begins in each for loop:
private static void testWithThreads() {
final Worker worker = new Worker();
new Thread(() -> {
System.out.println("start read thread");
for (int i = 0; i < 20; i++) {
worker.readData();
// any thread can now invoke writeData() if current thread is before next invocation of worker.readData();
}
try {
Thread.currentThread().join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
System.out.println("start write thread");
for (int i = 0; i < 20; i++) {
worker.writeData();
// any thread can now invoke readData() if current thread is before next invocation of worker.writeData();
}
try {
Thread.currentThread().join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
If you want to have better interleaving you can do one of these things:
use wait() and notify()
do not use synchronization on that methods - synchronize the
data.
move the sleep operation outside the synchronized write and read methods,
they will give the threads more chance to get into the
synchronized block.

Active Time of Thread Java

How Can I get active time of Thread for which it was actually in running state. Minus all the Waiting and Sleeping time.
I didn't seem to find anything in Thread API that gives me desired results.
If not exact code any ideas or Pseudo Codes would be great start.
Thanks
Thanks assylias
The ThreadMXBean worked for me.. Here is sample code of what I did.
#Override
public void run() {
System.out.println(Thread.currentThread().getName());
try {
for(int i = 999999999; i > 0; i--){}
Thread.sleep(5000);
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
long threadCpuTime = threadBean.getCurrentThreadCpuTime();
System.out.println(Thread.currentThread().getName() + " :: " + threadCpuTime);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
}
I Put up a sleep of 5 seconds just to check if it was added to CPU time. It wasn't added. Also I put up empty for loop so that processing takes some time.
Here's Output
Thread-1 :: 15600200
Thread-4 :: 15700100
Thread-3 :: 15600100
Thread-0 :: 15500100
Thread-2 :: 0

Categories