【问题标题】:Is it possible to create a high-priority thread with a regular JVM, one that wil not be preempted by any other thread?是否可以使用常规 JVM 创建一个不会被任何其他线程抢占的高优先级线程?
【发布时间】:2012-04-12 14:21:15
【问题描述】:

所以我的目标很简单:我想在不使用 RTSJ(Real-Time Java VM)或其他一些专有 JVM 的情况下在 Java 中创建一个高优先级线程。假设您从不创建任何垃圾,因此 GC 不会是罪魁祸首。假设我有 4 个处理器。可行吗?如果没有,是否可以计算我的线程被抢占了多少次?

@Gray:我希望以尽可能少的延迟获得尽可能多的实时响应,而无需使用 RTSJ 和特殊的操作系统

@sarnold:你说的很对。如果您在 JVM 级别完成此操作,但您的 JVM 没有被操作系统抢占,那么您在较低级别会遇到同样的问题。让我们假设可以破解和/或使用调整为不这样做的 linux 发行版。

@StephenC:我已经知道这是不可能的。这就是为什么我想这样做。 :) 如果我至少可以检测到抢占,我将有办法衡量我的进度。

【问题讨论】:

  • 这对我来说很像过早的优化。您要求的是普通 JVM 不提供的东西。您能否编辑您的问题并解释为什么您需要这样做?
  • 您是只对 JVM 级别的抢占感兴趣,还是对 OS 级别的抢占也感兴趣?
  • @sarnold - 如果您在谈论 HotSpot,则两者之间没有区别。所有 HotSpot Java 线程的调度和抢占都是由操作系统执行的。
  • @StephenC:很酷。当我上次真正使用 Java 时,GreenThreads 似乎是未来的浪潮。

标签: java multithreading optimization garbage-collection real-time


【解决方案1】:

是的,这是可能的!但是隔离 cpu 内核使其不会被任何用户或内核进程抢占 是与您的应用程序无关的操作系统配置。完成此操作后,您可以使用诸如CoralThreads 之类的线程关联库将您的线程固定到隔离的 cpu 内核。这大大减少了方差。下面是一个简单的代码示例,让你明白:

import com.coralblocks.coralthreads.Affinity;

public class Basics {

    public static void main(String[] args) throws Exception {

        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {

                // must be the first thing inside the run method
                Affinity.bind();

                try {

                    while(true) {

                        // do whatever you want here...
                    }

                } finally {

                    // must be the last thing inside the run method
                    Affinity.unbind(); 
                }
            }
        }, "MyPinnedThread");

        System.out.println();
        Affinity.printSituation(); // nothing done yet...

        // assign thread to processor:
        int procToBind = Integer.parseInt(args[0]);
        Affinity.assignToProcessor(procToBind, thread);

        Affinity.printSituation(); // now you see it there...

        // start the thread!
        thread.start();

        Affinity.printSituation(); // now it is running with a pid...
    }
}

输出:

$ java -cp coralthreads-all.jar com.coralblocks.coralthreads.sample.Basics 2

CpuInfo: [nChips=1, nCoresPerChip=4, hyper-threading=true, nProcessors=8, procIds=0,1,2,3,4,5,6,7]

Chip-0:
    Core-0:
        Processor-0: free
        Processor-4: free
    Core-1:
        Processor-1: free
        Processor-5: free
    Core-2:
        Processor-2: free
        Processor-6: free
    Core-3:
        Processor-3: free
        Processor-7: free

CpuInfo: [nChips=1, nCoresPerChip=4, hyper-threading=true, nProcessors=8, procIds=0,1,2,3,4,5,6,7]

Chip-0:
    Core-0:
        Processor-0: free
        Processor-4: free
    Core-1:
        Processor-1: free
        Processor-5: free
    Core-2:
        Processor-2: assigned to MyPinnedThread (not-started)
        Processor-6: free
    Core-3:
        Processor-3: free
        Processor-7: free

CpuInfo: [nChips=1, nCoresPerChip=4, hyper-threading=true, nProcessors=8, procIds=0,1,2,3,4,5,6,7]

Chip-0:
    Core-0:
        Processor-0: free
        Processor-4: free
    Core-1:
        Processor-1: free
        Processor-5: free
    Core-2:
        Processor-2: bound to MyPinnedThread (running pid=2180)
        Processor-6: free
    Core-3:
        Processor-3: free
        Processor-7: free

【讨论】:

    【解决方案2】:

    没有。标准 Java 不支持。

    我希望以尽可能少的延迟获得尽可能多的实时响应,而无需使用 RTSJ 和特殊的操作系统

    “尽可能少的延迟”不是可量化的要求。

    但是,正如我和其他人在回答您在该领域的许多问题时所说的那样,JavaSE 不是为这类事情而设计的,并且不/不能提供任何延迟保证。实际上,通用 Java 核心库的许多方面都指定,以明确在标准 Java 平台上没有与性能相关的保证。

    关于这个特定的问题,Java 线程规范说线程优先级只是建议性的。不能保证高优先级线程不会被低优先级线程抢占。实际的线程调度和切换策略由宿主操作系统实现,超出 Java 的控制范围。

    让我们假设可以破解和/或使用调整为不这样做的 linux 发行版。

    如果您做出这样的假设,您也可以直接破解操作系统以使线程调度程序等按照您的意愿行事......假设它在技术上是可行的。但也要注意,该级别的黑客行为可能会导致应用程序(如 JVM)出现意料之外的问题,这些问题并非旨在处理(例如)阻止 GC 运行的不可抢占线程。

    如果我至少可以检测到抢占,我将有办法衡量我的进度。

    Java 线程无法检测到它已被抢占,或者另一个 Java 线程已被抢占。我不认为 JVM 使用的操作系统级别的原生线程 API 支持这一点。

    【讨论】:

    • 这个是可以做到的,以前也做过。没有什么是不可能的。 :)
    • @SergioOliveiraJr。我没有说这是不可能的。如果您有时间和技能来修改 JVM / 操作系统以按照您希望的方式运行,那么一切皆有可能(理论上)。
    • 请解释否决票。如果是你@JohnPristine,就这么说吧,我将不再回答你的问题。
    • 顺便提一下,sched_setscheduler(2) 可用于将进程置于SCHED_FIFOSCHED_RR 优先级类中——它们只能被更高优先级的实时调度进程抢占。 (因此,在运行sshbash 的同时以更高的优先级运行它,这样您就可以解决问题。:)
    • @StephenC:哦,比这更容易; sched_setscheduler(2) 调用将 pid 作为参数,因此可以在其他进程上调用它。 schedtool(8) 是一种在另一个进程(类似于renice(1))上设置调度类的简单机制,以防您对编写自己的包装器不感兴趣。如果你确实想写一个包装器,它应该是简单的 JNI,不需要 JVM 摆弄。
    【解决方案3】:

    我相信你正在寻找这个:http://en.wikipedia.org/wiki/Real_time_Java 常规 Java 不提供这种能力。

    【讨论】:

    • 他非常了解 RTSJ,因为他特别提到了without using RTSJ。还是很真实的:)
    • 是的。我回答的第二部分是没有其他选择:)
    猜你喜欢
    • 2014-11-26
    • 2014-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-17
    • 2010-12-12
    • 2021-05-11
    相关资源
    最近更新 更多