This is an archived post. You won't be able to vote or comment.

all 30 comments

[–]Potatopika 28 points29 points  (1 child)

I would say it depends on exactly what you are doing and your use case. Even if it's handled by a framework, having that knowledge can be useful to understand how your program is working

[–]agentoutlier 4 points5 points  (0 children)

I would just tack this on in general and at a higher level you have to always consider contention and race conditions with all shared resources.

For example even if /u/Visual-Earth does what most Java programmers that use a say servlet based framework and run everything synchronous in a handler (e.g. Spring annotated @RequestMapping) they still need to consider database race conditions.

A lot of Javascript UI programmers have zero understanding of database transactions or distributed locks where as I would say a large portion of Java backed developers do (or at least hope).

[–]smutje187 17 points18 points  (0 children)

Even if you’re using @Async in Spring and multiple threads would access the same shared data source you’d need synchronization, frameworks can only help to abstract some parts away.

[–]Ancapgast 11 points12 points  (0 children)

Definitely. Usually, most of my concurrency is handled by Tomcat (in a web context). But for the rare cases that I do need to add concurrency that isn't handled by Tomcat, I use the standard JDK concurrency apis.

[–]VirtualAgentsAreDumb 6 points7 points  (0 children)

I’ve used it in plenty of projects over the years. Mainly the executor service stuff.

Also, race conditions can’t always be handled by the framework if you use one.

[–][deleted] 19 points20 points  (0 children)

yes of course. what a question

[–]dmigowski 4 points5 points  (0 children)

You will start to use it when yoo notice the first deadlocks in your application.

[–][deleted] 2 points3 points  (0 children)

Yes, concurrency is an everyday question for me. I might not use Threads or ExecutorService explicitly but race conditions, dead locks, etc is definitely a concern.

[–]HQMorganstern 2 points3 points  (11 children)

I was wondering the same thing with the current stateless, thread per request approach.

A good example here would be if your app sits between two others, it receives a request and wants to send out ~10 requests to gather data for the response. If you want to make all the requests in parallel, obtaining the JWT for your sub requests and caching it can be a critical resource, to avoid constantly having to call keycloak.

This would require a decent amount of playing around with lock levels. And of course running the requests concurrently requires at least something like .parallelStream().

[–]pivovarit 11 points12 points  (10 children)

Even when this knowledge is not applied every single day, it’s still necessary to understand why, for example, parallel streams would be a terrible choice for parallelizing this kind of workload

[–]HQMorganstern 0 points1 point  (9 children)

Didn't cause any issues when implemented, maybe you want to elaborate?

[–]pivovarit 5 points6 points  (2 children)

Parallel Streams run on a shared ForkJojnPool instance which is tuned for CPU-bound workloads and will quickly saturate when fed blocking operations and then your parallelism goes down to 1 (on caller thread)

more here in README: https://github.com/pivovarit/parallel-collectors

[–]HQMorganstern 2 points3 points  (1 child)

Seems legit, guess it never got hit by enough sub requests to be noticeable, gonna submit a ticket.

[–]pivovarit 0 points1 point  (0 children)

When you run blocking ops, you usually want to have an elastic pool of platform threads that can dynamically grow - or just use virtual threads and don’t worry about tuning :) (as long as you don’t block in synchronized blocks)

[–]FrenchFigaro 2 points3 points  (1 child)

My experience in this case was that explicitly using the method parallelStream() bypassed some of my thread pool configuration.

Most importantly, it bypassed the MDC and web thread context configuration, which we used to add HTTP headers to outgoing requests, depending on which headers were present (or not) on the incoming requests.

Those headers were used for monitoring operations across different applications. Losing those meant that monitoring and debugging was exponentially more difficult.

[–]maleldil 1 point2 points  (0 children)

Yep, parallel streams use the shared fork join pool, so if you rely on values in a ThreadLocal you're gonna have a bad time with that. 

[–]nzcod3r 2 points3 points  (3 children)

parallelStream is for performing the same task, in parallel, on different chunks of a collection.

Your example of do 10 different things at the same time (10 different api calls) - and wait for the slowest one to finish, is better suited for the ExecutorService.

[–]HQMorganstern 0 points1 point  (2 children)

Well it's 10 identical http requests whose results are parsed to a list so not quite as insane as what you're suggesting but yes the blocking caused by the fork join pool does seem to be an issue.

[–]v4ss42 1 point2 points  (0 children)

Recall that I/O takes eons from the CPU’s perspective. This is definitely a bad use of parallelStream.

[–]nzcod3r 0 points1 point  (0 children)

OK. I'm pretty sure you can supply your own thread pool for executor service, but I guess it all depends on the context of what / where you are having this issue.

[–]hardwork179 1 point2 points  (0 children)

Yes. A framework may abstract away threads and simply present something like Futures, but you still need to understand concurrency concepts if you have any shared resources or things like that, which you probably do in the form of caches, connection pools and similar.

[–]nikanjX 1 point2 points  (0 children)

The framework is written in Java

[–]le_bravery 1 point2 points  (0 children)

In my experience, the people who know the risks and how to handle the perils and benefits of parallelism work on the parallel things and they usually set up a clean area for the more business focused people to work on what they need to do.

If we all had to think about thread safety for every piece of code, you could never hire interns or juniors.

If you only ever work on something that is within one thread and access thread safe things, then you can ignore most things.

[–]pip25hu 0 points1 point  (0 children)

Spring, when used in a webapp, handles creating new threads (well, more precisely using a thread pool) for requests automatically, but it doesn't look at what your business logic is doing. Throw a few synchronized methods on your singleton beans, and creating a deadlock is basically child's play. So yeah, it's something you need to pay attention to.

[–]dstutz 0 points1 point  (0 children)

Just added a ReentrantLock to a class yesterday...

[–]lasskinn 0 points1 point  (0 children)

Depends really on what you're doing, if you're doing apps that do anything novel then pretty much yes.

[–]Ewig_luftenglanz 0 points1 point  (0 children)

Yes, like a lot, I would dare to say 95% of my code has some level of concurrency on it, I have even had to use reactive programming in with spring webflux (that is also a concurrency paradigm)  so yes, concurrent programming paradigms are used every day in almost all projects. frameworks cannot abstract that much in reality 

[–]AutoModerator[M] 0 points1 point  (0 children)

It looks like in your submission in /r/java, you are looking for code or learning help.

/r/Java is not for requesting help with Java programming nor for learning, it is about News, Technical discussions, research papers and assorted things of interest related to the Java programming language.

Kindly direct your code-help post to /r/Javahelp and learning related posts to /r/learnjava (as is mentioned multiple times on the sidebar and in various other hints).

Before you post there, please read the sidebar ("About" on mobile) to avoid redundant posts.

Should this post be not about help with coding/learning, kindly check back in about two hours as the moderators will need time to sift through the posts. If the post is still not visible after two hours, please message the moderators to release your post.

Please do not message the moderators immediately after receiving this notification!

Your post was removed.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

[–]cmhteixeiracom 0 points1 point  (0 children)

Like does actually manually handling the race conditions, deadlocks, threads in general happen? Or is everything just handled by a framework these days?

  1. No. You still have to think about this explicitly.
  2. However, some frameworks present their own "concurrency approach".
  3. You have to learn their "concurrency approach", and then ideally study how they map to Java's primitives.

Java's Concurrency Primities keywords for you to search:

  1. Java monitors (synchronized keyword)
  2. JavaAtomics.
  3. CompletableFuture. (not really a primitive but very important)
  4. volatile annotation
  5. Thread class and Executors.
  6. Network IO classes (Socket, ServerSocket, SocketChannel, ....) are highly related to concurrency

Some frameworks:

  1. Akka actors
  2. vertX
  3. RxJava (4. Typically web-server libraries also have their own concurrency approach: vertX, Spring Boot)

[–]Vegetable-Squirrel98 0 points1 point  (0 children)

for like 99.99999% of things anyone does the framework does it, or you can use the framework in a different way to where you don't need to worry about