Clojure 2024状态调查!分享您的想法。

欢迎!请参阅关于页面,了解如何使用本网站的更多信息。

0投票
Clojure

目前还没有一种简单的方法来优雅地关闭代理,同时确保所有提交的操作都已完成,且不会发送新的操作。

这里有一种简单的方法:

(shutdown-agents)

这个方法的两个问题:
1) 它将丢弃所有已提交但尚未开始执行的操作。
2) 它不会阻止向代理发送更多操作(不仅不会抛出错误,只是默默忽略)。

以下是一个证明:

`
(def my-agent (agent 1))

(defn sleep-and-inc [number]
(Thread/sleep 3000)
(println "操作编号" number "完成")
(inc number))

(println "发送两次")
(send-off my-agent sleep-and-inc)
(send-off my-agent sleep-and-inc)
(println "发送完成")

(shutdown-agents)
(println "请求关闭")

(println "第三次发送")
(send-off my-agent sleep-and-inc)
(println "发送完成")
`

以下是输出:

发送两次 发送完成 请求关闭 第三次发送 发送完成 操作编号 1 完成

如您所见,第二次操作被丢弃,第三次操作被忽略。

顺便说一句,shutdown-agents 的文档说明具有误导性(不明确)。
"...运行的操作将会完成,但不再接受新的操作..."
1) 它没有说明关于已提交的操作的任何内容。
2) "不再接受新的操作"听起来应该会抛出错误,但实际上却被默默忽略。
因此,更好的文档应说明:"...运行的操作将会完成,等待的操作将会被丢弃,新的操作将会被忽略..."

一个类似的方法在Java中工作得很好:

`
ExecutorService executor = Executors.newSingleThreadExecutor();

    executor.submit(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("Action 1 complete");
        }
    });
    executor.submit(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("Action 2 complete");
        }
    });

    executor.shutdown();
    System.out.println("Shutdown requested");

// //将会抛出RejectedExecutionException
// executor.submit(new Runnable() {
// @Override
// public void run() {
// try {
// Thread.sleep(3000);
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
// System.out.println("操作3完成");
// }
// });
`

输出

请求关闭 操作1完成 操作2完成

我说"工作得很好",是指以下两点:
1) 它将完成所有等待的任务(不仅仅是运行中的任务)。
2) 在调用"shutdown"之后,如果再提交新任务,将会抛出错误。

所以回到Clojure,我们现在只剩下这个习惯用语(并不简单!):

(await my-agent) (shutdown-agents)

这不是一个简单直接的习惯用语,因为:
1) 您需要跟踪系统中的所有代理。如果使用第三方代码并使用代理,则几乎不可能做到这点。
2) 如果在等待或关闭期间发送另一个操作,它甚至不会抛出异常。

提案
(受Java的启发)
1) 创建一个名为"shutdown-agents-gracefully"的新函数,它将执行两项额外的操作:
1.1) 将代理系统置于"正在关闭"状态
1.2) 完成运行动作以及等待动作
2) 修改“send”和“send-off”,使其在代理系统处于“关闭”状态下抛出错误。
3) 修复“shutdown-agents”的文档字符串(见上述内容)

当这个Jira工单被验证通过后,我将开始开发补丁。

1 答案

0投票
by
参考:https://clojure.atlassian.net/browse/CLJ-1920(由metaruslan报告)
...