[英]Java executor model that allows running tasks only on instantiating thread
I am writing a multithreaded application where I've got the situation that I have certain library-related methods that can only be run on the main-thread
. 我正在编写一个多线程应用程序,在这种情况下,我遇到了某些只能 在 main-thread
上运行的与库相关的方法。 Currently I am running a simple, self-written, solution that listens on a queue for tasks and then executes them serially as they come in. 目前,我正在运行一个简单的,自编写的解决方案,该解决方案在队列中侦听任务,然后在传入任务时依次执行它们。
This works so far although it gets ugly when I need return values etc. (Which I am currently solving the c-way by passing along datastructures with the tasks and then have a busy-loop checking if the structure has been written to on the site of the method that queues a task. 到目前为止,这仍然有效,尽管当我需要返回值等时很难看。(目前我正在通过传递带有任务的数据结构来解决c方式,然后进行忙循环检查该结构是否已在现场写入将任务排队的方法。
This is not really the cleanest solution, and while it works, I was hoping to find a better way of doing this.. 这确实不是最干净的解决方案,并且在可行的同时,我希望找到一种更好的方法。
Q : Is there anything in the JDK or in a single specialized library that does what I need? 问 :JDK或单个专用库中是否有我需要的东西? Or is there any programming pattern that addresses my needs in a clean and structured way? 还是有任何一种编程模式可以干净整洁地满足我的需求?
A possible solution with CompletableFuture
: 使用CompletableFuture
的可能解决方案:
class Job<T> {
private final Supplier<T> computation;
private final CompletableFuture<T> future;
Job(Supplier<T> computation, CompletableFuture<T> future) {
this.future = future;
this.computation = computation;
}
public Supplier<T> getComputation() {
return computation;
}
public CompletableFuture<T> getFuture() {
return future;
}
}
public void client() {
// on the client:
CompletableFuture<String> future = new CompletableFuture<>();
Supplier<String> computation = () -> "Here I am!";
enqueue(new Job<>(computation, future));
String resultString = future.get();
}
public <T> void server(Job<T> job) {
// on the server; job is taken from the queue
CompletableFuture<T> future = job.getFuture();
future.complete(job.getComputation().get());
}
Here, on the client, future.get()
will wait infinitely until the result is available. 在这里,在客户端上, future.get()
将无限期等待直到结果可用。 There is also another form: 还有另一种形式:
future.get(1, TimeUnit.MINUTES)
would only wait for one minute and then return. 只会等待一分钟,然后返回。 This for can be used for polling. 可以用于轮询。
Let your main thread plays role of an Executor: 让您的主线程扮演执行者的角色:
static ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(10);
public static void main(String... args) {
// initialization...
for (;;) {
queue.take().run();
}
}
Whenever you need to execute a task on the main thread, put it to the queue: 每当需要在主线程上执行任务时,请将其放入队列:
queue.add(()->methodCall(1,2,3));
I'm not sure how you are time-slicing the main thread, but what you are saying is that you want to run some jobs using multiple threads and other jobs on the main thread sequentially. 我不确定您如何对主线程进行时间切片,但是您要说的是要使用多个线程来运行某些作业,而要在主线程上依次运行其他作业。
Simplest answer would be to use two different work queues - one which is serviced by multiple threads and one which is serviced by only the main thread. 最简单的答案是使用两个不同的工作队列-一个由多个线程提供服务,一个仅由主线程提供服务。
This would make both queues easier to understand and use. 这将使两个队列更易于理解和使用。
Also, jobs running on either queue should implement an interface that requires them to expose a method that returns a reference to the resulting data - this might be the actual results or a file name or an input stream attached to the file containing the results. 同样,在任一队列上运行的作业都应实现一个接口,该接口要求它们公开返回对结果数据的引用的方法-这可能是实际结果,也可能是文件名或附加到包含结果的文件的输入流。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.