用Java限制线程的CPU /内存使用率?

Ale*_*ley 42 java memory cpu multithreading throttling

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

对于C++也存在类似的问题,但我想尽可能避免使用C++和JNI.我意识到使用更高级别的语言可能无法做到这一点,但我很想知道是否有人有任何想法.

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

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

它的编写方式,重构为每个执行的类创建单独的进程将是一件痛苦的事.如果这是通过VM参数限制内存使用的唯一好方法,那么就这样吧.但是我想知道是否有办法用线程来做.即使作为一个单独的进程,我也希望能够以某种方式限制其CPU使用率,因为正如我之前提到的,其中一些将立即执行.我不想要一个无限循环来占用所有资源.

编辑3:一种简单的近似对象大小的方法是使用java的Instrumentation类; 特别是getObjectSize方法.请注意,使用此工具需要一些特殊设置.

aka*_*okd 32

如果我理解你的问题,一种方法是自适应地睡眠线程,就像用Java完成视频播放一样.如果你知道你想要50%的核心利用率,你的算法应该睡眠大约0.5秒 - 可能在一秒钟内分布(例如0.25秒计算,0.25秒睡眠等).这是我视频播放器的一个例子.

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));
Run Code Online (Sandbox Code Playgroud)

此代码将根据帧/秒值休眠.

为了节省内存使用量,您可以将对象创建包装到工厂方法中,并使用某种具有有限许可的信号量作为字节来限制估计的总对象大小(您需要估计各种对象的大小以定义信号量) ).

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();
    }
}
Run Code Online (Sandbox Code Playgroud)


Mic*_*rdt 5

您可以通过JMX获得有关CPU和内存使用情况的大量信息,但我认为它不允许任何主动操作.

要在某种程度上控制CPU使用率,可以使用Thread.setPriority().

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


And*_*rew 5

关心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
}
Run Code Online (Sandbox Code Playgroud)