Регулировка ЦП/использования памяти Потока в Java?

M-x customize-group, затем скажите ему, что Вы хотите настроить scheme. Блуждайте по странице немного, и Вы будете видеть "Название программы Схемы", которое можно изменить, если интерпретатор схемы не называют scheme.

можно также найти Шарлатана полезным - http://www.neilvandyke.org/quack/

42
задан Community 23 May 2017 в 12:34
поделиться

9 ответов

Если я понимаю вашу проблему, одним из способов было бы адаптивно засыпать потоки, подобно тому, как воспроизведение видео выполняется в 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));

Этот код будет переходить в спящий режим на основе значения кадров в секунду.

Чтобы ограничить использование памяти, вы можете заключить создание объекта в фабричный метод, и использовать какой-то семафор с ограниченными разрешениями в качестве байтов, чтобы ограничить общий предполагаемый размер объекта (вам необходимо оценить размер различных объектов, чтобы нормировать семафор).

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();
    }
}
32
ответ дан 26 November 2019 в 23:58
поделиться

Вы можете получить много информации об использовании ЦП и памяти через JMX , но я не думаю, что он позволяет какие-либо активные манипуляции.

Для управления использованием ЦП до некоторой степени вы можете использовать Thread.setPriority () .

Что касается памяти, не существует такой вещи, как поточная память. Само понятие потоков Java означает разделяемую память. Единственный способ контролировать использование памяти - использовать параметры командной строки, такие как -Xmx, но нет возможности управлять настройками во время выполнения.

5
ответ дан 26 November 2019 в 23:58
поделиться

Вы можете назначить разные приоритеты потокам, чтобы наиболее релевантный поток планировался чаще.

Посмотрите на этот ответ , чтобы узнать, поможет ли это.

Когда все запущенные потоки имеют одинаковый приоритет, они могут работать следующим образом:

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

Когда вы назначаете другой приоритет одному из них это может выглядеть так:

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

То есть первый поток выполняется «чаще», чем остальные.

1
ответ дан 26 November 2019 в 23:58
поделиться

Thread.setPriority () может помочь, но не позволяет ограничить использование ЦП потоком. Фактически, я не слышал о какой-либо библиотеке Java, которая бы это делала.

Возможно, можно было бы реализовать такое средство при условии, что ваши потоки готовы к сотрудничеству. Ключ состоит в том, чтобы потоки периодически вызывались в настраиваемый планировщик, а планировщик отслеживал использование ЦП потока с помощью JMX. Но проблема в том, что если какой-то поток не выполняет вызов планировщика достаточно часто, он может превысить пределы регулирования. И вы ничего не можете поделать с потоком, который застревает в цикле.

Еще один теоретический способ реализации - использовать Isolates. К сожалению, вам будет сложно найти JVM общего назначения, реализующую изоляты. Кроме, стандартные API-интерфейсы позволяют контролировать только изолятор, но не потоки в изоляторе.

0
ответ дан 26 November 2019 в 23:58
поделиться

Единственный способ ограничить использование ЦП потоков - это заблокировать ресурс или часто вызывать yield ().

Это не ограничивает использование ЦП ниже 100%, но дает другие потоки и обрабатывает больше временных интервалов.

0
ответ дан 26 November 2019 в 23:58
поделиться

Забота о форумах 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
}
5
ответ дан 26 November 2019 в 23:58
поделиться

Если вы запускаете потоки в отдельном процессе, вы можете ограничить использование памяти и ограничьте количество процессоров или измените приоритет этих потоков.

Однако все, что вы сделаете, скорее всего, приведет к увеличению накладных расходов и сложности, что часто приводит к обратным результатам.

Если вы не объясните, почему вам это нужно (например, у вас есть плохо написанная библиотека, которой вы не доверяете и не можете получить поддержку) Я бы посоветовал вам это не делать.

Причина, по которой нелегко ограничить использование памяти, заключается в том, что используется только одна куча. Таким образом, объект, который используется в одном потоке, может использоваться в другом и не назначается тому или иному потоку.

Ограничение использования ЦП означает остановку всех потоков, чтобы они ничего не делали, однако лучший подход - убедиться, что потоки не тратят впустую ресурсы ЦП и активны только для выполнения работы, которую необходимо выполнить, и в этом случае вы не захотите останавливать их в выполнении.

1
ответ дан 26 November 2019 в 23:58
поделиться

Почему бы вместо "многопоточности" не использовать совместную многозадачность, Было бы интересно посмотреть, сможете ли вы манипулировать http://www.janino.net/ , чтобы запустить программу в течение определенного времени / набора инструкций, а затем остановить и запустить следующую программу. По крайней мере, так это честно, дайте всем один и тот же отрезок времени ...

1
ответ дан 26 November 2019 в 23:58
поделиться

Чтобы уменьшить нагрузку на ЦП, вы хотите, чтобы ваши потоки находились внутри общих циклов if и while .

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

Сон на несколько сотен миллисекунд приведет к значительно уменьшить использование ЦП с незначительным или незаметным результатом в производительности.

Что касается памяти, я бы запустил профилировщик для отдельных потоков и сделал некоторую настройку производительности. Если вы ограничили объем памяти, доступной для потока, я думаю, что вероятно исключение нехватки памяти или голодание потока. Я бы доверил JVM предоставить столько памяти, сколько требуется потоку, и работать над сокращением использования памяти, сохраняя в области видимости только важные объекты в любой момент времени.

-1
ответ дан 26 November 2019 в 23:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: