2012-01-08 2 views
4

В программе, над которой я работаю, я хочу, чтобы пользователь мог вводить количество потоков обработки, которые имеет их процессор, чтобы программа могла разделить рабочую нагрузку (она делает общие вычисления) между количеством потоков, компьютер есть.Как создать определенное пользователем количество потоков?

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

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

for(int i = 0; i < threads; i++) { 

    Thread thread(i) = new Thread(){ 
     public void run() { 
      double endNum = 0; 

      for(double numberRun = 0; numberRun <= calcs/threads; numberRun++){ 
       endNum += (num * 999999999); 
      } 

      System.out.println("Thread " + i + " complete! The numerical result of the calculation is " + endNum); 
     } 
    }; 
} 

Все, кто не уверен, что я говорю, я пытаюсь создать несколько потоков, что компьютер, иначе количество ядер, или, если он использует Intel, HyperThreading, в два раза количество ядер. У вас может быть больше потоков, чем система может выполнять сразу, но я пытаюсь сделать самую эффективную вещь и делить общее количество вычислений на количество потоков, которые система может выполнять одновременно. Я не знаю, как дать пользователю определить количество потоков, а затем создать это число потоков (или позволить программе определить количество потоков, которые система имеет, а затем создать это число).

+6

Вы проверили это: http://stackoverflow.com/questions/1980832/java-how-to-scale-threads-according-to-cpu-cores – home

+0

Это не имело бы смысла, если вы также не прикололи их к ядро/HT, но даже тогда вы должны знать, что ваши потоки не будут одинокими в современной многозадачной ОС, поэтому в большинстве случаев вам намного лучше позволить планировщику операционной системы решить, что нужно запускать и когда. Это будет неплохо работать, тогда как у вас нет способа узнать, что делают другие потоки в системе, и риск ухудшения производительности, если вы смогли привязать один из ваших потоков к ядру, занятому чем-то другим. – Fredrik

+0

@Fredrik - для задач с интенсивным процессором (и считая, что это единственный или самый распространенный на машине), вы вообще не хотите запускать больше потоков, чем у вас есть процессоры, иначе вы просто создаете конкуренцию. Но вы также не хотите подрезать количество процессоров, потому что вы не будете использовать их все. nCPUIntensiveThreads == nПроцессоры на самом деле довольно справедливая цель. – James

ответ

0

Количество потоков не зависит от процессора. Если вы используете один процессор, ваша программа будет переходить из одного потока в другой.

Итак, в вашем методе нет ничего «неправильного» (конечно, если вы будете использовать его правильно).

+0

Оптимальное количество потоков, безусловно, зависит от количества процессоров, если вы собираетесь что-то связать с процессором и критиковать производительность. – James

+0

@James, так что это зависит от производительности процессора. –

0

Я думаю, вы спрашиваете о МАКСИМАЛЬНОМ числе потоков, которые может иметь система?

Как обсуждалось here, нет максимального количества потоков, которые может иметь система (так как Java-программы запускаются внутри виртуальной машины Java, ограничение, которое у вас будет, - это виртуальная машина Java JVM). Ограничение на количество ресурсов, которые вы можете выделить на свои потоки.

Если вы спрашиваете, сколько потоков в данный момент выполняется (возможно, это было запущено какой-либо внешней программой или внутри JVM), вы, вероятно, можете это узнать, но я думаю, что это не будет используйте для своего случая, поскольку нитки, которые вы запускаете, никак не связаны с другими потоками, запущенными в системе!

+0

На практике вы можете почти определенно выделить больше потоков, чем вы можете разумно использовать. После более чем нескольких тысяч вы начнете тратить довольно значительное количество процессора, просто переключаясь между ними. – James

1

то, что мне нравится использовать, является Исполнитель-исполнитель = Executors.newFixedSizeThreadPool (int numberOfThreads);

, а затем у вас есть executor.execute (myRunnable) ваши runnables :) В этом подходе вы несете ответственность за создание потоков, и у вас есть гарантия, что вы не создаете ненужные потоки.

, но как вы могли бы выяснить, сколько потоков вы должны использовать, это зависит от вас, чтобы исследовать.

4

Вы можете узнать, сколько процессоры доступны для JVM, как это:

Runtime.getRuntime().availableProcessors() 

Оптимальное число нитей для расщепления чисто числовой расчет более вероятно один на один процессор.Если какой-либо из этих потоков приходится время от времени блокировать IO, это может быть больше.

+0

Но как я могу создать количество потоков, которые есть на компьютере пользователя? Это предназначено для работы во множестве различных системных конфигураций, и программа должна автоматически создавать нужное количество потоков. – user1137371

+0

@ user11373731 - Я думаю, что вы смешиваете слова потоков и процессоров в своих комментариях. Вышеупомянутая команда сообщила вам количество доступных процессоров - это также количество потоков, которые вы хотите, в целом. – James

+0

@James - Я знаю, что количество процессоров - это количество нужных вам потоков, но я не знаю, как заставить программу выполнять вычисления по этому числу потоков, как только она определит, сколько из них будет использоваться на основе результат из этого фрагмента кода. – user1137371

2

Если вы собираетесь выполнение кучу различных различных задач - в противоположность попытке разделить одну большую задачу на несколько более мелких задач, работающих параллельно, вы можете захотеть использовать Executor:

Executor e = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); 
// run a single task 
e.execute(new Runnable() { 
    public void run() { 
     // do stuff here 
    } 
}); 

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

+0

Я пытаюсь разделить один большая задача (неоднократно выполняющая уравнение) между всеми доступными потоками обработки. – user1137371

+0

@ user1137371 Тогда не имеет значения, используете ли вы потоки напрямую или используете исполнителя, хотя мне все еще нравится последний из-за Futures. В теле Runnable вы можете использовать тело метода из своего вопроса, а значением 'threads' будет' Runtime.getRuntime(). AvailableProcessors() '(или что-то, что вы сочтете нужным.) – millimoose

3
class Task implements Runnable { 
    Task(/** Whatever you need to identify the subset of tasks to run goes here*/) { 

    } 

    public void run() { 
    // do the calcs 
    } 
} 

int nProcs = Runtime.getRuntime().getAvailableProcessors(); 

Task[] tasks = new Task[nProcs]; 
for (int i = 0; i < nProcs; i++) { 
    tasks[i] = new Task(/** Whatever parameters for this batch*/); 
    new Thread(tasks[i]).start(); 
    // Alternatively, use Executors.newFixedThreadPool() to get a service above, and submit the runnable there, getting a future for the result, something like this: 
    Future f = executor.submit(task[i]); 
} 

}

+0

James, есть ли что я могу написать вам об этом по электронной почте? У меня есть пара вопросов и некоторый код, о котором было бы трудно говорить здесь. Если у вас есть время, напишите мне по адресу [email protected] – user1137371

1

Мне кажется, что то, что вы ищете также отображение стратегия задач в нитки. Например, цикл, такие как:

for(int i = 0; i < LARGE_NUMBER; i++) { 
    f(i); 
} 

может быть преобразован в параллельную версию как:

class Task implements Runnable { 
    private int i; 

    public Task(int i) { 
     this.i = i; 
    }  

    public void run() { 
     f(i); 
    } 
} 

затем заменить исходный для петли с:

ExecutorService exec = Executors.newCachedThreadPool(); 
for(int i = 0; i < LARGE_NUMBER; i++) { 
    exec.submit(new Task(i)); 
} 

exec.awaitTermination(1000, TimeUnit.HOURS); // wait for all tasks to finish 

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

Смежные вопросы