许多现代语言都支持在语言级别使用协程。 Java当前不支持协程,但是希望将来会有所改变。
在C ++ 20中,计划引入对使用协程的支持。
使用JNI,我们可以用C ++编写协程并在Java代码中使用。
让我们考虑一下可以编写哪些本机协程以及如何在Java代码中使用它们。
生成器允许您创建某种类型的值序列,而这些值是延迟和同步生成的。
generator<int> generate(int count) { for (int i = 0; i < count; i++) { co_yield i; } }
Generator<Integer> gen1 = Coroutine.yield(5); Generator<Float> gen2 = Coroutine.yield(1f, 5); Generator<Double> gen3 = Coroutine.yield(v -> v * 2, 1d, 5); for (int item : gen1) { System.out.println("yield value: " + item); }
异步生成器允许您创建某种类型的值序列,而这些值是延迟和异步生成的。
async_generator<int> generate(int count) { for (int i = 0; i < count; i++) { co_await 1s; co_yield i; } }
Generator<Integer> gen1 = Coroutine.yieldAsync(5); Generator<Float> gen2 = Coroutine.yieldAsync(1f, 5); Generator<Double> gen3 = Coroutine.yieldAsync(v -> v * 2, 1d, 5); for (int item : gen1) { System.out.println("yield value: " + item); }
任务执行异步计算,这是延迟执行的,而协程直到任务显式启动才执行。
协程可以用作光流。 在这种情况下,可以限制系统中正在运行的线程数,例如,不超过1000个。协程可以根据需要运行。
启动协程时,将检查其是否准备就绪。 如果没有,协程将暂停,操作系统将处理程序传递给它。 此时,将执行一段有用的代码。 准备好协程后,将进行协程更新。
struct awaiter { bool await_ready() const { return false; } void await_resume() {} void await_suspend(std::coroutine_handle<> handler) { if (!handler.done()) { handler.resume(); } } }; co_await awaiter{};
与启动线程时一样,您可以将Runnable或Callable传递给协程。
Coroutine.await(() -> { int sum = 5 + 10; }); Task<Integer> task = Coroutine.await(() -> { int sum = 5 + 10; return sum; });
计时器将当前任务暂停所需的时间。
auto operator co_await(const std::chrono::system_clock::duration& duration) { return timer{duration}; } co_await 10ms;
可以替代Thread.sleep()。
Coroutine.await(10, TimeUnit.MILLISECONDS);
协程还可以用于编写非阻塞代码以与文件系统,网络等配合使用。
如您所见,协程使编写异步代码更加容易,从而使部分代码得以执行而不会阻塞流。
他们计划从C ++ 20开始的协程将显示为纯语言功能。
计划将生成器,任务和其他协程添加到C ++ 23标准或更高版本中。
您可以自己编写协程,也可以使用现成的库,例如
cppcoro 。
编译器MVSC,Clang已经支持协程作为扩展,而GCC才处于开发阶段。
完整的源代码可以在github上查看:
code