If I have only one Akka actor that I create at the start of my program, is every message I tell that actor processed sequentially, on a single thread? So if I have multiple threads telling that actor to do different tasks, is it essentially the same thing as having multiple threads queue up tasks on Java's Executor.newSingleThreadExecutor?
An actor processes messages sequentially and (in Akka, at least) presents a single-threaded illusion (that is to say that under the hood, the dispatcher may execute the actor's logic on different threads from message to message, but from the actor's perspective there's only one thread).
If there's only one actor, the message processing is effectively the same thing as queueing up tasks in a single threaded executor (with the potential extra benefit that each executed task can affect the execution of subsequent tasks by changing how the actor responds to a message).
Accordingly, an actor all by itself is not that useful an abstraction; put a lot of actors into a system where they can collaborate and you have something that is surprisingly useful and powerful.
Related
I get that with threads being nonblocking, we don't need to have Thread sprawl depending on N concurrent requests, but rather we put our tasks in a single event loop in our reactive web programming pattern.
Yes, that can help, but since the event loop is a queue, what if the first task to be processed blocks forever? Then the event loop will never progress and thus end of responses and processing other than queueing more tasks. Yes, timeouts are probably possible, but I can't wrap my head around how the event loop can be a good solution.
Say you have 3 tasks that take 3 seconds to wait for IO and run each executions and they got submitted to the event queue. Then they will still take 9 seconds to be able to be processed and also to execute once IO resolved. In the case of making threads that block, this would have resolved in 3 seconds since they run concurrently.
Where I can see a benefit is if the event loop is not really a queue and upon signal that a task is ready to be processed, it dispatches that task to be processed. In that case though, this would mean that order of task execution is not maintained and also each task has to still be running a thread in order to be able to tell when IO is resolved.
Maybe I am not understanding the event loop and thread handling correctly. Can someone correct me please because it seems like this Reactor pattern seems to make things possibly worse.
Lastly, upon X requests in Spring Reactor, does only 1 thread get created to run handlers instead of the traditional X threads? In that case, if someone accidently wrote blocking code, doesnt that mean each subsequent requests get queued?
It is not a good idea to use the event loop for long running tasks. This is considered an anti-pattern. Usually it is merely used for quickly picking up imminent events, but not actually doing the work associated with these events if the work would block the event loop noticeably. You would want to use a separate thread pool for executing long running tasks. So the event loop would usually only initiate work using asynchronous and hence non-blocking structures (or actually doing the work only if it can be done very quickly) and pass the heavier and possibly blocking tasks to a separate thread pool (for CPU intensive computations) or to the operating system (such as data buffers to be sent over the network).
Also, don't be fooled by the fact that only one thread is dealing with the events, it is very fast and is usually enough for even demanding applications. Platforms like NodeJS or frameworks like Netty (used in Akka, Play framework, Apache Cassandra, etc.) are using an event loop at their heart with great success. One should just be aware of the fact, that performing blocking operations inside the event loop is generally a bad idea.
Please have a look at some of these posts for more information:
The reactor pattern and non blocking IO
Unix Network Programming
Kotlin Webflux
Slightly off topic but still a very prominent example: Don't Block the Event Loop (NodeJS)
I started reading Vert.x framework documentation, but i didn't understand how it works and what is a Reactor pattern, i read this article https://dzone.com/articles/understanding-reactor-pattern-thread-based-and-eve and noticed that instead of general servlet based (one request one thread) approch, Reactor pattern uses event-driven architecture where single thread named event loop takes a request put it to some sort of the job queue and provides a handler that will be executed once the task has been finished , and code in handler will be executed by this event loop, so golden rule is - don't block event loop.
What I don't understand is , from article:
Those handlers/callbacks may utilize a thread pool in multi-core environments.
So handlers use thread pool , how this pool is difference from the standard thread pool for example Servlet's container TOMCAT. How these two concepts are different from each other in case of Http server if both are using Thread pool to manage requests.
Thank in advance
Forget that DZone article. Forget the Reactor pattern. Learn Asynchronous procedure call.
There are 2 ways to split all the work in computer to parts: threads and tasks (in Java- tasks are Runnables). Tasks execute on a thread pool when they are ready. And when they are not ready, they do not occupy thread with its huge stack, and we can afford to have millions of tasks in single JVM instance, while 10000 threads in single JVM instance is problematic.
The main problem with tasks is when task needs data which is not ready (not calculated by other task, or not yet arrived via network). In the thread world, the thread waiting for data executes a blocking operation like inputsream.read(), but tasks are not allowed to do this, or they would have occupied too many threads from thread pool and all advantages of task-based programming would be lost. So tasks are augmented with mechanisms which submit that task to the thread pool exactly when all their parameters arrived. Task with such a mechanism is called asynchronous procedure call. All the event-driven architectures are variants of asynchronous procedure call: Vert.x, RxJava, Project Reactor, Akka Actors etc. They just pretend to be something original and not always talk about this.
lets say we have two threads with are connected by a ConcurrentLinkedQueue. What I want is something like a handler on the queue so that one thread knows when the other queue has added soemthing to the queue and to poll it. Is that possible?
Normally a ConcurrentLinkedQueue is used when there is at least one producer on a thread, and at least one consumer on a different thread.
The consumer will process the element as soon as they are available, to do so the read operation on the queue blocks, sometimes for a limited amount of time.
Depending on the application you can have a single producer and many consumer, or viceversa.
Blocking achieves exactly your requirement (the consumer thread knows when an element is inserted).
The fact that the consumer thread blocks is not a problem unless is your main process thread or unless you are planning to build several hundred concurrent consumers.
So, Queue#take() or Queue#poll(long timeout,TimeUnit unit) is your friend here, if you just run it on dedicated Thread.
Consider an application which uses an in-memory FIFO Java queue to deposit objects that will be subsequently processed by a thread, executing in parallel with many other threads (e.g., as part of a ThreadPool).
Each object must be processed by a "compatible" thread and that compatibility is assured via checking a label associated with the object (i.e., each thread can process certain types of objects, not all of them). If a thread reads an object from the queue and the label it reads is not among the ones it supports, it has to ignore the object.
Some additional characteristics the application has to fulfill:
In-order processing (i.e., all objects with the same label should be processed in the order they are deposited in the queue).
High performance (i.e., capable of processing thousands of rather "heavy" objects per second).
One could use the ConcurrentLinkedQueue, as suggested in an earlier question, but a single queue makes things tricky for segregating the input per label. Alternatively, each thread could be assigned with handling a single label, so it could have its own non-concurrent queue. Or maybe another approach should be followed.
What would be the best way to implement the above specification?
If a thread reads an object from the queue and the label it reads is not among the ones it supports, it has to ignore the object.
Does that mean that some of the tasks that go into the queue will never be performed? And does it mean that there's no way to predict which ones will be ignored and which ones will be processed?
That doesn't sound like a very good design.
If that's not what you meant, then maybe "ignored" was not the right word.
Each object must be processed by a "compatible" thread ... all objects with the same label should be processed in the order they are deposited in the queue
I'm not going to try to guess what could be different about the different kinds of worker threads, but If I was given that requirement, I would have a different thread pool for each different kind of worker. Then it becomes the responsibility of whoever generates the tasks to put them in the right queue.
Why would a thread reject a task based upon the object's label?
The thread that picks up the task from the queue must act like a worker thread. You must design/write in a manner, that the thread picks up the object (or task) from the queue, reads its label, and processes it based on its label.
You must not have a any correspondence between a object type and a thread type. Each thread should be written to handle any object.
A question on using threads in java (disclaimer - I am not very experienced with threads so please allow some leeway).
Overview:
I was wondering whether there was a way for multiple threads to add actions to be performed to a queue which another thread would take care of. It does not matter really what order - more important that the actions in the queue are taken care of one at a time.
Explanation:
I plan to host a small server (using servlets). I want each connection to a client to be handled by a separate thread (so far ok). However, each of these threads/clients will be making changes to a single xml file. However, the changes cannot be done at the same time.
Question:
Could I have each thread submit the changes to be made to a queue which another thread will continuously manage? As I said it does not matter on the order of the changes, just that they do not happen at the same time.
Also, please advise if this is not the best way to do this.
Thank you very much.
This is a reasonable approach. Use an unbounded BlockingQueue (e.g. a LinkedBlockingQueue) - the thread performing IO on the XML file calls take on the queue to remove the next message (blocking if the queue is empty) then processing the message to modify the XML file, while the threads submitting changes to the XML file will call offer on the queue in order to add their messages to it. The BlockingQueue is thread-safe, so there's no need for your threads to perform synchronization on it.
You could have the threads submit tasks to an ExecutorService that has only one thread. Or you could have a lock that allows only one thread to alter the file at once. The later seems more natural, as the file is a shared resource. The queue is the implied queue of threads awaiting a lock.
The Executor interface provides the abstraction you need:
An object that executes submitted Runnable tasks. This interface provides a way of decoupling task submission from the mechanics of how each task will be run, including details of thread use, scheduling, etc. An Executor is normally used instead of explicitly creating threads."
A single-threaded executor service seems like exactly the right tool for the job. See Executors.newSingleThreadExecutor(), whose javadoc says:
Creates an Executor that uses a single worker thread operating off an
unbounded queue. (Note however that if this single thread terminates
due to a failure during execution prior to shutdown, a new one will
take its place if needed to execute subsequent tasks.) Tasks are
guaranteed to execute sequentially, and no more than one task will be
active at any given time. Unlike the otherwise equivalent
newFixedThreadPool(1) the returned executor is guaranteed not to be
reconfigurable to use additional threads.
Note that in a JavaEE context, you need to take into consideration how to terminate the worker thread when your webapp is unloaded. There are other questions here on SO that deal with this.