简体   繁体   English

在 Loom 中,我可以为 Recursive[Action/Task] 使用虚拟线程吗?

[英]In Loom, can I use virtual threads for Recursive[Action/Task]?

Is it possible to use RecursiveAction, for example, in conjunction with -- instead of the fork/join pool -- a pool of virtual threads (before I attempt a poorly-designed, custom effort)?例如,是否有可能将 RecursiveAction 与——而不是 fork/join 池——虚拟线程池结合使用(在我尝试设计不佳的自定义工作之前)?

RecursiveAction is a subclass of ForkJoinTask which is, as the name suggests and the documentation even says literally, an RecursiveActionForkJoinTask的子类,顾名思义,文档甚至字面意思是,一个

Abstract base class for tasks that run within a ForkJoinPool .抽象基础 class 用于在ForkJoinPool中运行的任务。

While the ForkJoinPool can be customized with a thread factory , it's not the standard thread factory , but a special factory for producing ForkJoinWorkerThread instances.虽然可以使用线程工厂自定义ForkJoinPool ,但它不是标准的线程工厂,而是用于生产ForkJoinWorkerThread实例的特殊工厂 Since these threads are subclasses of Thread , they can't be created with the virtual thread factory.由于这些线程是Thread的子类,因此无法使用虚拟线程工厂创建它们。

So, you can't use RecursiveAction with virtual threads.因此,您不能将RecursiveAction与虚拟线程一起使用。 The same applies to RecursiveTask .这同样适用于RecursiveTask But it's worth rethinking what using these classes with virtual threads would gain you.但是值得重新考虑将这些类与虚拟线程一起使用会给您带来什么。

The main challenge, to implement decomposition of your task into sub-task is on you, anyway.无论如何,将任务分解为子任务的主要挑战在于您。 What these classes provide you, are features specifically for dealing with the Fork/Join pool and balancing the workload with the available platform threads.这些类为您提供的是专门用于处理 Fork/Join 池和平衡工作负载与可用平台线程的功能。 When you want to perform each sub-task on its own virtual thread, you don't need this.当你想在它自己的虚拟线程上执行每个子任务时,你不需要这个。 So you can easily implement a recursive task with virtual threads without the built-in classes, eg因此,您可以在没有内置类的情况下使用虚拟线程轻松实现递归任务,例如

record PseudoTask(int from, int to) {
    public static CompletableFuture<Void> run(int from, int to) {
        return CompletableFuture.runAsync(
            new PseudoTask(from, to)::compute, Thread::startVirtualThread);
    }

    protected void compute() {
        int mid = (from + to) >>> 1;
        if(mid == from) {
            // simulate actual processing with potentially blocking operations
            LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(500));
        }
        else {
            CompletableFuture<Void> sub1 = run(from, mid), sub2 = run(mid, to);
            sub1.join();
            sub2.join();
        }
    }
}

This example just doesn't care about limiting the subdivision nor avoiding blocking join() calls and it still performs well when running, eg PseudoTask.run(0, 1_000).join();这个例子既不关心限制细分也不关心阻塞join()调用,它在运行时仍然表现良好,例如PseudoTask.run(0, 1_000).join(); You might notice that with larger ranges, the techniques known from the other recursive task implementations can be useful here too, where the sub-task is rather cheap.您可能会注意到,对于更大的范围,从其他递归任务实现中获知的技术在这里也很有用,其中子任务相当便宜。

Eg, you may only submit one half of the range to another thread and process the other half locally, like例如,您可能只将范围的一半提交给另一个线程并在本地处理另一半,例如

record PseudoTask(int from, int to) {
    public static CompletableFuture<Void> run(int from, int to) {
        return CompletableFuture.runAsync(
            new PseudoTask(from, to)::compute, Thread::startVirtualThread);
    }

    protected void compute() {
        CompletableFuture<Void> f = null;
        for(int from = this.from, mid; ; from = mid) {
            mid = (from + to) >>> 1;
            if (mid == from) {
                // simulate actual processing with potentially blocking operations
                LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(500));
                break;
            } else {
                CompletableFuture<Void> sub1 = run(from, mid);
                if(f == null) f = sub1; else f = CompletableFuture.allOf(f, sub1);
            }
        }
        if(f != null) f.join();
    }
}

which makes a notable difference when running, eg PseudoTask.run(0, 1_000_000).join();这在运行时会产生显着差异,例如PseudoTask.run(0, 1_000_000).join(); which will use only 1 million threads in the second example rather than 2 millions.在第二个示例中将仅使用 100 万个线程,而不是 200 万个。 But, of course, that's a discussion on a different level than with platform threads where neither approach would work reasonably.但是,当然,这是与平台线程不同级别的讨论,在平台线程中,这两种方法都无法合理地工作。


Another upcoming option is the StructuredTaskScope which allows to spawn sub-tasks and wait for their completion另一个即将推出的选项是StructuredTaskScope ,它允许生成子任务并等待它们完成

record PseudoTask(int from, int to) {
    public static void run(int from, int to) {
        try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
            new PseudoTask(from, to).compute(scope);
            scope.join();
        } catch (InterruptedException e) {
            throw new IllegalStateException(e);
        }
    }

    protected Void compute(StructuredTaskScope<Object> scope) {
        for(int from = this.from, mid; ; from = mid) {
            mid = (from + to) >>> 1;
            if (mid == from) {
                // simulate actual processing with potentially blocking operations
                LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(500));
                break;
            } else {
                var sub = new PseudoTask(from, mid);
                scope.fork(() -> sub.compute(scope));
            }
        }
        return null;
    }
}

Here, the tasks do not wait for the completion of their sub-task but only the root task waits for the completion of all tasks.在这里,任务不等待其子任务完成,而只有根任务等待所有任务完成。 But this feature is in incubator state, hence, may take even longer than the virtual threads feature, to become production-ready.但此功能在孵化器 state 中,因此可能需要比虚拟线程功能更长的时间才能投入生产。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法使用 Project Loom 的虚拟线程 - Not able us Virtual Threads using Project Loom Java 的 Project Loom 中的“Thread.sleep”与虚拟线程(纤维)是否不同 - Is `Thread.sleep` different with virtual threads (fibers) in Project Loom for Java Project Loom 虚拟线程会提高并行流的性能吗? - Will Project Loom Virtual Threads improve the perfomance of parallel Streams? Project loom:是什么让使用虚拟线程时性能更好? - Project loom: what makes the performance better when using virtual threads? 虚拟线程中的 TLAB - Project Loom - TLAB in Virtual Thread - Project Loom 我应该将线程用于任务处理器吗? - Should I use Threads for a Task Processor? 我如何才能使用多个线程作为客户端-谁都在switch语句中各自执行任务 - How can i make this use multiple threads as clients - who all perform a task each within the switch statement ForkJoinPool中递归任务和递归操作之间的区别 - Difference between recursive task and recursive action in ForkJoinPool 如何从动作侦听器运行具有多个线程的方法 - How can i run a method with multiple threads from action listener 我可以将2个线程的操作与一个空的锁定对象同步吗? - Can I synchronize an action of 2 threads with an empty lock object?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM