如何更改正在运行的 java 进程的优先级?

Posted

技术标签:

【中文标题】如何更改正在运行的 java 进程的优先级?【英文标题】:How to change the priority of a running java process? 【发布时间】:2011-09-08 12:13:52 【问题描述】:

在related question 中,我们探索了使用 ProcessBuilder 使用依赖于操作系统的命令以低优先级启动外部进程。我还发现,如果父进程是低优先级的,那么它的所有衍生进程都以低优先级启动。所以我的新问题是关于以低优先级启动一个java文件(通过双击windows中的可执行jar运行)或在运行期间以编程方式更改其优先级。我试过改变线程优先级,但这对windows进程优先级没有影响。

我尝试了以下,但它并没有改变任务管理器中的进程优先级

public class hello
    public hello()
        try
            Thread.currentThread().setPriority(1);
            Thread.sleep(10000);    
        catch(Exception e)e.printStackTrace();
    

我能想到的唯一另一件事是使用批处理文件运行程序,但可以这么说,我宁愿将其保留在家庭中。那么有谁知道基于java的方法来改变当前进程的优先级?理想情况下,如果能够在程序运行时更改进程的优先级以响应用户输入,那就太好了。

【问题讨论】:

在 Un*x 上,您可以调用另一个外部进程来重新调整或设置 CPU 亲和性等。看到这可以从命令行完成。不知道 Java 池的 Windows 端是如何工作的 :) @SyntaxT3rr0r 在 windows 中您需要 SetPriorityClass msdn.microsoft.com/en-us/library/ms686219%28v=vs.85%29.aspx 您可以从 JNI/JNA 或一些命令行实用程序(如 gilchrist.ca/jeff/SetPriority/index.html)调用 @bestsss:谢谢,很有趣。在某种程度上是有道理的:我认为大多数 API 调用可以在/如果默认情况下不存在时被“包装”在命令行实用程序中。 :) @SyntaxT3rr0r,不知道大多数情况,有些可能需要由同一进程执行。我已经有十年没有做 WinAPI 的东西了(我想)。 【参考方案1】:

对于 Windows 10,您仍然可以通过 已弃用 WMIC 命令将运行进程设置为低优先级:

static void setSelfLowPrio()
    try 
        Runtime.getRuntime()
                .exec(String.format("wmic process where processid=%d CALL setpriority \"idle\"", ProcessHandle.current().pid()));
     catch (IOException e) 
        e.printStackTrace();
    

如果“空闲”不足以满足您的进程,您也可以将其设置为“低”或“低于正常”。

【讨论】:

【参考方案2】:

(标题没有专门针对窗口,但标签可以。但是我认为了解差异可能是相关的。)

一般来说,进程的线程调度是依赖于内核的特性,几乎没有可移植的方式来做到这一点。事实上,优先级的含义差别很大。例如,在 NT 上,高值 24 表示实时,值 1 表示空闲。在 unix 上则相反:1 是最快的,较大的值是较慢的。

当然,Java 使用范围为 1 (lowest) 到 10 (highest) 的 .setPriority 抽象出这些信息。

还有一点没有指出,但在许多 unix 上一个相当大的问题是: 默认情况下,用户不能提高进程的优先级(即降低 nice 值),即使用户自己降低了进程的优先级。优先权。

相比之下,在 NT 上,我认为您可以将优先级重新提高到默认优先级。

简单地说:.setPriority 可能适用于 Windows,但很可能不适用于 unix。

【讨论】:

Thread.setPriority 与 Windows 或 Unix 进程优先级完全无关。这只是关于内部 Java 调度程序,并会在 Java 处于活动状态时更改线程运行的时间/频率 - 但不会像 OP 所要求的那样更改与其他进程相比 Java 的运行频率。 Java(热点)没有用于线程管理的“内部 Java 调度程序”。它依赖于操作系统的线程优先级。例如在 Windows 上它使用 SetThreadPriority WinAPI 函数 - hg.openjdk.java.net/jdk/jdk/file/151b990e3764/src/hotspot/os/…【参考方案3】:

也许您正在尝试为操作系统做一些事情。

在 Unix 中,在负载下,每个进程都有一个很短的时间片来完成它的工作。如果它使用了所有时间片,则假定该进程受 CPU 限制,它的优先级较低。如果它阻塞在 IO 上,则假定它是 IO 绑定的并且它的优先级被提高(因为它没有使用它所有的时间片)

这一切只有在没有足够的 CPU 时才有意义。如果您在大多数情况下将 CPU 负载保持在 100% 以下,则每个进程都将获得所需的 CPU,并且优先级不会有太大区别。

【讨论】:

好点,感谢您的回复。然而,我正在编写的程序运行并维护了许多耗电的进程。连续几天以 100% 的速度运行是理想的,但这些都在我的家用 PC 上,所以能够不时使用我的电脑真是太好了。因此需要动态改变优先级。该程序有时也可能会进行时间敏感计算,因此在需要时更改为更高优先级的能力也非常实用。 如果你有时间敏感的程序,你能做的最重要的事情就是在机器上单独运行应用程序。即使你有一个实时操作系统,你也会在负载下得到巨大的抖动。 “所有这一切只有在没有足够的 CPU 时才重要”是关于这个问题的不准确陈述;进程优先级与操作顺序有关,与 CPU 使用率无关。较高优先级的进程能够在事件被传递给较低优先级的进程之前使用它们。 @Wayne 只是那些事件同时发生。如果有空闲 cpu,则线程可以运行而不管优先级如何。如果没有足够的cpu,你的操作系统可以做出选择。 "系统以循环方式将时间片分配给所有具有最高优先级的线程。如果这些线程都没有准备好运行,则系统以循环方式将时间片分配给具有次高优先级的所有线程。”可在此处获取:msdn.microsoft.com/en-us/library/windows/desktop/…【参考方案4】:

https://***.com/questions/257859 讨论了如何在 Windows 中更改线程的优先级。我不知道有任何 Java API 可以做到这一点,因此您将不得不依靠 JNI 来调用 Windows API。在您的情况下,我想我会从 JNA 开始,它可以让您轻松映射函数,或者找到一个现成的 Java 包装器到 API(如果有的话)。

【讨论】:

以上是关于如何更改正在运行的 java 进程的优先级?的主要内容,如果未能解决你的问题,请参考以下文章

我可以在线程执行时更改线程的优先级。更改是发生还是os忽略它?(Java)

线程优先级

Linux进程概念与管理

Linux进程与作业管理

进程优先级

进程设置优先级啥作用?