Background:
I am creating library that I want to make open source.
This library is designed for use in backend processes.
The service I will make available utilizes Java's ProcessBuilder, to execute several native commands.
This service will often finish processing commands in under 1 second, but in rare cases, may take several minutes.
Questions:
In a situation where a public library has methods that may become blocking, should the library provide an async option for calling that method? Or should such a library remain unopinionated, and leave that to the users to implement?
Here are a couple ways of how I have been thinking of implementing this service...
Example 1: unopinionated
SomeService, with blocking method- if user wants to run asynchronously, they must figure it out
SomeService.java
public class SomeService {
public Response process(Request request) {
//do stuff for 60 seconds
}
}
Example 2: opinionated
SomeService, with blocking method- optional
SomeProcessTask, which users can utilize to bypass blocking method and run async.
SomeProcessTask.java
public class SomeProcessTask implements Callable<Response> {
private final Request request;
public SomeProcessTask(Request request) {
this.request = request;
}
@Override
public Response call(Request request) {
//do stuff for 60 seconds
}
}
SomeService.java
public class SomeService {
public Response process(Request request) {
SomeProcessTask task = new SomeProcessTask(request);
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Response> future = executor.submit(task);
return future.get();
}
}
You commented:
Then you most definitely should not attempt making your library run concurrently. Concurrency is tricky. An example is the code seen in the Question; multiple concurrency problems have been identified in the Comments.
Keep your library simple. Focus on its core purpose. Let the calling programmer deal with concurrency if they deem it important.
You should document for the calling programmer any aspects of your library that may impact its use concurrently. Most especially, mention any issue that would contraindicate its use with virtual threads. Such issues include:
synchronizedblocks. (Or else re-implement those withReentrantLock.)To learn more about concurrency, read the book Java Concurrency in Practice by Brian Goetz et al. And study the Java Memory Model.
To learn about virtual threads, see talks by Ron Pressler, Alan Bateman, or José Paumard.