3

I have been thinking about why JDBC is only blocking operation and why I can't set some listener to the hypothetical event handler onResultSetArrived(ResultSet rs). Why I have to block single one thread per each JDBC query.

After a while I've dive into Java Sockets (I suppose JDBC is build on top of them) and realised that there also isn't any event handling. Only option to provide non-blocking read is through the available() method but this is very inefficient as it has to be checked periodically in the loop.

As far as I'm aware, interruption is fundamental thing in PC. It goes down from the hardware up to the operating system. In the Java it can be implemented into event driven approach in read value from Socket.

Now, my question is am I missing something and there exists some workaround or current architecture in Java really is one thread per one blocking operation? And if yes isn't it inefficient?

  • "current architecture in Java really is one thread per one blocking operation" - For blocking I/O, yes. However, Project Loom is bringing Fibers and Continuations to Java which will make it **much** more efficient :) – Jacob G. Jul 29 '18 at 18:37

2 Answers2

1

In Java, you can have many threads. A thread is doing its stuff until it is blocked somewhere (typically, on a mutex or a I/O operation). Of course, this does not block other threads.

The fundamental scenario of multithreaded applications is that you use multiple threads when waiting for a blocked thread would introduce too much waiting. Definition of "too much" here depends entirely on you, but in general, this is how you achieve beter performance through better utilization of resources.

There are some limitations in how threads in Java work, however. Most, if not all of them are when the thread is blocked somewhere "outside" of Java such as in OS call or external (native) library. Theoretically, if native code blocks a thread, Java can not do anything about it. Normally, this should not be a problem unless the native code has a bug.

So in the case of a blocking JDBC response, you would create a new thread which would do other work while first thread is waiting for database to complete. Alternatively, you could make a thread just for doing JDBC. You could make it exactly like you want (with listeners etc.) except for limitations imposed by OS. So it's possible, but it's probably not provided out-of-the-box by JDBC drivers. There is a lot of infrastructure already in core Java which you might find useful (thread pools, workers, synchronized collections). But as with any multithreading, you need to be very careful with accessing data from different threads simultaneously.

Since Java 7, there is also support for non-blocking I/O (NIO). This is almost exactly what you are describing. I/O is offloaded to OS, so your operations return immediately and you get a callback when the operation is finished. However, not all libraries support NIO. For my work, I have never had a reason to use it, because I could always implement the same stuff with my threads at least as good.

jurez
  • 4,436
  • 2
  • 12
  • 20
  • As far as I'm aware one thread means instant 1MB of memory consumed (on 32bit it was 512kb). So if you will have 1000 requests at once and each request in addition will be run in async manner consuming another 6 threads it will gives you 6000MB of RAM consumed even if this threads are just idling because of waiting for some blocking operation. You can serve this requests perhaps with only 1 thread but instead you have 6000 threads. And I'm not expert in threading but what about performance? Something will have to switching between this large amount of threads. – Jiří Kačírek Jul 29 '18 at 17:29
  • Sure, switching threads incurs some overhead, but this is unavoidable in any case. The general rule is to use as few threads as possible. In case of JDBC, having more than few threads is unlikely to give any additional performance improvement. The best way would be to make a pool of work and pool of threads which take work from the pool. Such asynchronous mechanisms work extremely well if you implement them properly. – jurez Jul 29 '18 at 17:34
  • Why as few threads as possible for JDBC? If one request to DB will take 200ms second because DB is on another server and there is some latency then you need lot of threads and all will be in blocking state most of the time. I think there aren't any excuse to Java. Current architecture is just obsolete and that's all. There is some ADBA movenet in Oracle which should provide async variant of JDBC but it's 2018 and it's still not completed!!! – Jiří Kačírek Jul 29 '18 at 17:55
  • I guess I wasn't clear enough. You want to match the number of threads to the useful work - not less, not more. But there are a lot more things to consider here. In short, I see a lot of architectural limitations in Java, but I wouldn't say this is one of them. You can implement a very efficient solution yourself - so the limitation is your lack of knowledge, not something in Java. – jurez Jul 29 '18 at 18:10
  • Well you are right I lack knowledge but I know pretty well that that no matter what solution somebody will develop it will be still a and always just a workaround for Java lacking async in JDBC. – Jiří Kačírek Jul 29 '18 at 18:19
  • What different it is if somebody else implements it or if you implement it? Maybe you could do it and sell it if you think there is a market for it! JDBC is just a standard, Java has nothing to do with it, any actual JDBC code is provided by database vendors. – jurez Jul 29 '18 at 18:33
1

If the question is whether the "current architecture in Java really is one thread per one blocking operation" and by "blocking operation" you mean "database operation" then the answer is no. Most database drivers available for Java currently are jdbc-based and do work that way. But there are usable alternatives (https://spring.io/blog/2016/11/28/going-reactive-with-spring-data) and more on the way ( https://blogs.oracle.com/java/jdbc-next:-a-new-asynchronous-api-for-connecting-to-a-database , https://dzone.com/articles/spring-5-webflux-and-jdbc-to-block-or-not-to-block). For how this works see How is ReactiveMongo implemented so that it is considered non-blocking?

For jdbc there are also ways to wrap the jdbc calls (Wrapping blocking I/O in project reactor , Spring webflux and reading from database ) and projects pursuing this approach (https://dzone.com/articles/myth-asynchronous-jdbc)

Ryan Dawson
  • 11,832
  • 5
  • 38
  • 61