在Java中调节线程的CPU /内存使用率?

我正在编写一个应用程序,它将运行多个线程,并希望限制这些线程的CPU /内存使用量。

对于C ++有一个类似的问题 ,但是我想尽量避免使用C ++和JNI。 我意识到这可能不会使用更高级别的语言,但我很好奇,看看有没有人有任何想法。

编辑:增加了一个赏金; 我想要一些非常好的,深思熟虑的想法。

编辑2:我需要这个的情况是在我的服务器上执行其他人的代码。 基本上它是完全的任意代码,唯一的保证就是在类文件上会有一个主要的方法。 目前,在运行时加载的多个完全不同的类正在作为单独的线程同时执行。

写它的方式,重构为每个被执行的类创build单独的进程将是一个痛苦。 如果这是通过VM参数来限制内存使用的唯一好方法,那就这样吧。 但是我想知道是否有办法用线程来完成。 即使作为一个单独的过程,我想能够以某种方式限制其CPU使用率,因为如前所述,其中几个将立即执行。 我不想要一个无限循环来占用所有的资源。

编辑3:一个简单的方法来近似对象的大小是与java的Instrumentation类; 具体来说就是getObjectSize方法。 请注意,使用此工具需要一些特殊设置。

如果我理解你的问题,一种方法是自适应地睡眠线程,类似于Java中的video回放。 如果你知道你需要50%的核心利用率,那么你的algorithm应该睡眠大约0.5秒 – 可能在一秒之内分配(例如0.25秒计算,0.25秒睡眠等)。 这里是我的video播放器的一个例子 。

long starttime = 0; // variable declared //... // for the first time, remember the timestamp if (frameCount == 0) { starttime = System.currentTimeMillis(); } // the next timestamp we want to wake up starttime += (1000.0 / fps); // Wait until the desired next time arrives using nanosecond // accuracy timer (wait(time) isn't accurate enough on most platforms) LockSupport.parkNanos((long)(Math.max(0, starttime - System.currentTimeMillis()) * 1000000)); 

此代码将基于帧/秒的值进行睡眠。

为了节制内存的使用,你可以将你的对象创build封装到一个工厂方法中,并使用某种限制许可的信号量作为字节来限制估计的总体对象大小(你需要估计各种对象的大小来配给信号量)。

 package concur; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; public class MemoryLimited { private static Semaphore semaphore = new Semaphore(1024 * 1024, true); // acquire method to get a size length array public static byte[] createArray(int size) throws InterruptedException { // ask the semaphore for the amount of memory semaphore.acquire(size); // if we get here we got the requested memory reserved return new byte[size]; } public static void releaseArray(byte[] array) { // we don't need the memory of array, release semaphore.release(array.length); } // allocation size, if N > 1M then there will be mutual exclusion static final int N = 600000; // the test program public static void main(String[] args) { // create 2 threaded executor for the demonstration ExecutorService exec = Executors.newFixedThreadPool(2); // what we want to run for allocation testion Runnable run = new Runnable() { @Override public void run() { Random rnd = new Random(); // do it 10 times to be sure we get the desired effect for (int i = 0; i < 10; i++) { try { // sleep randomly to achieve thread interleaving TimeUnit.MILLISECONDS.sleep(rnd.nextInt(100) * 10); // ask for N bytes of memory byte[] array = createArray(N); // print current memory occupation log System.out.printf("%s %d: %s (%d)%n", Thread.currentThread().getName(), System.currentTimeMillis(), array, semaphore.availablePermits()); // wait some more for the next thread interleaving TimeUnit.MILLISECONDS.sleep(rnd.nextInt(100) * 10); // release memory, no longer needed releaseArray(array); } catch (InterruptedException e) { e.printStackTrace(); } } } }; // run first task exec.submit(run); // run second task exec.submit(run); // let the executor exit when it has finished processing the runnables exec.shutdown(); } } 

你可以通过JMX得到很多有关CPU和内存使用情况的信息,但我不认为它允许任何主动的操作。

为了在一定程度上控制CPU使用率,可以使用Thread.setPriority() 。

至于内存,没有每线程内存的东西。 Java线程的概念意味着共享内存。 控制内存使用的唯一方法是通过像-Xmx这样的命令行选项,但在运行时无法操作设置。

关心Java论坛 。 基本上定时执行,然后等待你花费太多时间。 正如在原始线程中提到的,在一个单独的线程中运行这个函数并中断工作线程将会给出更准确的结果,并且随着时间的推移将取平均值。

 import java.lang.management.*; ThreadMXBean TMB = ManagementFactory.getThreadMXBean(); long time = new Date().getTime() * 1000000; long cput = 0; double cpuperc = -1; while(true){ if( TMB.isThreadCpuTimeSupported() ){ if(new Date().getTime() * 1000000 - time > 1000000000){ //Reset once per second time = new Date().getTime() * 1000000; cput = TMB.getCurrentThreadCpuTime(); } if(!TMB.isThreadCpuTimeEnabled()){ TMB.setThreadCpuTimeEnabled(true); } if(new Date().getTime() * 1000000 - time != 0) cpuperc = (TMB.getCurrentThreadCpuTime() - cput) / (new Date().getTime() * 1000000.0 - time) * 100.0; } //If cpu usage is greater then 50% if(cpuperc > 50.0){ //sleep for a little bit. continue; } //Do cpu intensive stuff } 

您可以为线程分配不同的优先级,以便最相关的线程更频繁地进行调度。

看看这个答案 ,看看是否有帮助。

当所有正在运行的线程具有相同的优先级时,它们可以像这样运行:

 t1, t2, t3, t1, t2, t3, t1, t2, t3 

当您为其中一个分配不同的优先级时,可能如下所示:

 t1, t1, t1, t1, t2, t1, t1, t1 t3. 

也就是说,第一个线程“更经常地”运行。

如果在单独的进程中运行线程,则可以限制内存使用量并限制CPU数量或更改这些线程的优先级。

但是,您所做的任何事情都可能会增加费用和复杂性,而这往往是适得其反的。

除非你可以解释你为什么要这样做(例如,你有一个不好的书架,你不信任,不能得到支持),我build议你不需要。

它不容易限制内存使用的原因是只有一个共享的堆。 所以在一个线程中使用的对象可以在另一个线程中使用,而不是分配给一个线程或另一个线程。

限制CPU的使用意味着停止所有的线程,所以他们什么都不做,但是更好的方法是确保线程不会浪费CPU,而只是在做需要完成的工作,在这种情况下你不会想阻止他们这样做。

为什么不用“线程化”来做合作式的多任务处理,看看你是否可以操纵http://www.janino.net/来运行程序一定的时间/集合,然后停止运行下一个节目。; 至less这样它的公平,给每个人同一时间片…

Thread.setPriority()可能有帮助,但是它不允许你限制线程使用的CPU。 实际上,我还没有听说过有这样的Java库。

只要你的线程准备好合作,就可能实现这样的设施。 关键是让线程定期调用自定义调度程序,并使调度程序使用JMX监视线程CPU使用情况。 但问题是,如果某个线程没有足够频繁地调用调度程序,则可能会超出限制。 而且,对于陷入循环中的线程,您无能为力。

另一个实施的理论途径是使用隔离。 不幸的是,你将很难find一个实现分离的通用JVM。 此外,标准API只允许您控制隔离区,而不是隔离区内的线程。

限制线程CPU使用率的唯一方法是通过阻塞资源或经常调用yield()。

这不会将CPU使用率限制在100%以下,但会给其他线程和进程提供更多的时间片。

为了减lessCPU,你想睡在普通的ifwhile循环中。

 while(whatever) { //do something //Note the capitol 'T' here, this sleeps the current thread. Thread.sleep(someNumberOfMilliSeconds); } 

睡几百毫秒将大大减lessCPU使用率,几乎没有明显的性能结果。

至于内存,我会在个别线程上运行一个分析器,并进行一些性能调优。 如果你扼杀的线程可用的内存量,我认为可能是内存不足或内存不足。 我相信JVM可以提供尽可能多的内存,并且可以在任何给定的时间内只保留重要的对象,从而减less内存使用量。