Java 只允许 运行 任务在实例化线程上的执行器模型
Java executor model that allows running tasks only on instantiating thread
我正在编写一个多线程应用程序,在这种情况下,我有某些与库相关的方法可以 仅 运行在 main-thread
上。目前我正在 运行 一个简单的、自写的解决方案,它在队列中侦听任务,然后在任务进入时串行执行它们。
虽然它在我需要 return 值等时变得丑陋,但到目前为止它仍然有效。(我目前正在通过将数据结构与任务一起传递来解决 c-way,然后进行忙循环检查是否该结构已写入任务排队方法的站点。
这并不是最干净的解决方案,虽然它有效,但我希望找到更好的方法..
Q:JDK 或 单一专业化 库中是否有任何东西可以满足我的需要?或者是否有任何编程模式可以以干净和结构化的方式满足我的需求?
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());
}
此处,在客户端,future.get()
将无限等待直到结果可用。还有一种形式:
future.get(1, TimeUnit.MINUTES)
只会等一分钟然后return。这个for可以用来轮询
让你的主线程扮演执行者的角色:
static ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(10);
public static void main(String... args) {
// initialization...
for (;;) {
queue.take().run();
}
}
每当您需要在主线程上执行任务时,将其放入队列:
queue.add(()->methodCall(1,2,3));
我不确定你是如何对主线程进行时间切片的,但你的意思是你想 运行 一些使用多个线程的作业和主线程上的其他作业顺序。
最简单的答案是使用两个不同的工作队列 - 一个由多个线程提供服务,一个仅由主线程提供服务。
这将使两个队列更易于理解和使用。
此外,任一队列上的作业 运行ning 应该实现一个接口,该接口要求它们公开一个方法,该方法 returns 对结果数据的引用 - 这可能是实际结果或文件名称或附加到包含结果的文件的输入流。
我正在编写一个多线程应用程序,在这种情况下,我有某些与库相关的方法可以 仅 运行在 main-thread
上。目前我正在 运行 一个简单的、自写的解决方案,它在队列中侦听任务,然后在任务进入时串行执行它们。
虽然它在我需要 return 值等时变得丑陋,但到目前为止它仍然有效。(我目前正在通过将数据结构与任务一起传递来解决 c-way,然后进行忙循环检查是否该结构已写入任务排队方法的站点。
这并不是最干净的解决方案,虽然它有效,但我希望找到更好的方法..
Q:JDK 或 单一专业化 库中是否有任何东西可以满足我的需要?或者是否有任何编程模式可以以干净和结构化的方式满足我的需求?
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());
}
此处,在客户端,future.get()
将无限等待直到结果可用。还有一种形式:
future.get(1, TimeUnit.MINUTES)
只会等一分钟然后return。这个for可以用来轮询
让你的主线程扮演执行者的角色:
static ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(10);
public static void main(String... args) {
// initialization...
for (;;) {
queue.take().run();
}
}
每当您需要在主线程上执行任务时,将其放入队列:
queue.add(()->methodCall(1,2,3));
我不确定你是如何对主线程进行时间切片的,但你的意思是你想 运行 一些使用多个线程的作业和主线程上的其他作业顺序。
最简单的答案是使用两个不同的工作队列 - 一个由多个线程提供服务,一个仅由主线程提供服务。
这将使两个队列更易于理解和使用。
此外,任一队列上的作业 运行ning 应该实现一个接口,该接口要求它们公开一个方法,该方法 returns 对结果数据的引用 - 这可能是实际结果或文件名称或附加到包含结果的文件的输入流。