جافا: كيفية قياس المواضيع وفقًا لنوى وحدة المعالجة المركزية؟

StackOverflow https://stackoverflow.com/questions/1980832

  •  22-09-2019
  •  | 
  •  

سؤال

أنا لست مبرمجًا جيدًا Java ، إنها هوايتي فقط ، لكنني حريصة على معرفة أكثر من متوسطة الأشياء.

أريد حل مشكلة رياضية مع عدة مؤشرات ترابط في Java. يمكن فصل مشكلة الرياضيات الخاصة بي إلى وحدات العمل ، والتي أريد حلها في العديد من المواضيع.

لكنني لا أريد أن يكون لدي كمية ثابتة من الخيوط التي تعمل عليها ، ولكن بدلاً من ذلك كمية من الخيوط إلى كمية مراكز وحدة المعالجة المركزية. ومشكلتي هي أنني لم أتمكن من العثور على برنامج تعليمي سهل في الإنترنت لهذا الغرض. كل ما وجدته هو أمثلة مع خيوط ثابتة.

فهل يمكنك مساعدتي في رابط إلى توتوري جيد أو هل يمكن أن تعطيني مثالاً سهلاً وجيدًا؟ أن يكون لطيفا حقا :)

هل كانت مفيدة؟

المحلول

يمكنك تحديد عدد العمليات المتاحة للجهاز الظاهري Java باستخدام طريقة وقت التشغيل الثابتة ، متاح المعالجات. بمجرد تحديد عدد المعالجات المتاحة ، قم بإنشاء هذا العدد من المواضيع وقم بتقسيم عملك وفقًا لذلك.

تحديث: لمزيد من التوضيح ، يعد مؤشر الترابط مجرد كائن في Java ، حتى تتمكن من إنشائه تمامًا كما لو كنت إنشاء أي كائن آخر. لذلك ، دعنا نقول أنك تسمي الطريقة أعلاه وتجد أنها تُرجع معالجتين. مدهش. الآن ، يمكنك إنشاء حلقة تنشئ مؤشر ترابط جديد ، وتقسيم العمل لهذا الخيط ، وتطلق النار من الخيط. إليكم بعض psuedocode لإظهار ما أعنيه:

int processors = Runtime.getRuntime().availableProcessors();
for(int i=0; i < processors; i++) {
  Thread yourThread = new AThreadYouCreated();
  // You may need to pass in parameters depending on what work you are doing and how you setup your thread.
  yourThread.start();
}

لمزيد من المعلومات حول إنشاء موضوع خاص بك ، توجه إلى هذا البرنامج التعليمي. أيضا ، قد ترغب في النظر إلى تجميع الموضوع لإنشاء المواضيع.

نصائح أخرى

ربما تريد أن تنظر إلى إطار عمل java.util.concurrent لهذه الأشياء أيضًا. شيء مثل:

ExecutorService e = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
// Do work using something like either
e.execute(new Runnable() {
        public void run() {
            // do one task
        }
    });

أو

    Future<String> future = pool.submit(new Callable<String>() {
        public String call() throws Exception {
            return null;
        }
    });
    future.get();  // Will block till result available

هذا أجمل كثيرًا من التعامل مع برك الخيوط الخاصة بك وما إلى ذلك.

لدى دوغ ليا (مؤلف الحزمة المتزامنة) هذه الورقة التي قد تكون ذات صلة:http://gee.cs.oswego.edu/dl/papers/fj.pdf

تمت إضافة Fork Join Framework إلى Java SE 7. فيما يلي بعض المراجع:

http://www.ibm.com/developerworks/java/library/j-jtp11137/index.htmlمقال لبريان جويتز

http://www.oracle.com/technetwork/articles/java/fork-join-422606.html

الخيار 1:

NewworkstealingPool من عند Executors

public static ExecutorService newWorkStealingPool()

ينشئ مجموعة خيوط لسرقة العمل باستخدام جميع المعالجات المتاحة كمستوى التوازي المستهدف.

مع واجهة برمجة التطبيقات هذه ، لا تحتاج إلى تمرير عدد من النوى ExecutorService.

تنفيذ واجهة برمجة التطبيقات هذه من Grepcode

/**
     * Creates a work-stealing thread pool using all
     * {@link Runtime#availableProcessors available processors}
     * as its target parallelism level.
     * @return the newly created thread pool
     * @see #newWorkStealingPool(int)
     * @since 1.8
     */
    public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

الخيار 2:

NewfixedThreadPool API من Executors أو other newXXX constructors, الذي يعود ExecutorService

public static ExecutorService newFixedThreadPool(int nThreads)

استبدال nthreads مع Runtime.getRuntime().availableProcessors()

الخيار 3:

Threadpoolexecutor

public ThreadPoolExecutor(int corePoolSize,
                      int maximumPoolSize,
                      long keepAliveTime,
                      TimeUnit unit,
                      BlockingQueue<Runnable> workQueue)

يمر Runtime.getRuntime().availableProcessors() كمعلمة ل maximumPoolSize.

الطريقة القياسية هي طريقة التشغيل. getRuntime (). في معظم وحدات المعالجة المركزية القياسية ، ستكون قد أعادت عدد الخيوط المثلى (وهو ليس عدد CPU Core الفعلي) هنا. لذلك هذا ما تبحث عنه.

مثال:

ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

لا تنسَ إغلاق خدمة المنفذ مثل هذا (أو لن يخرج البرنامج):

service.shutdown();

هنا مجرد مخطط سريع كيفية إعداد رمز MT المستقبلي (Offtopic ، للتوضيح):

CompletionService<YourCallableImplementor> completionService = 
    new ExecutorCompletionService<YourCallableImplementor>(service);
    ArrayList<Future<YourCallableImplementor>> futures = new ArrayList<Future<YourCallableImplementor>>();
    for (String computeMe : elementsToCompute) {
        futures.add(completionService.submit(new YourCallableImplementor(computeMe)));
    }

ثم تحتاج إلى تتبع عدد النتائج التي تتوقعها واستردادها مثل هذا:

try {
  int received = 0;
  while (received < elementsToCompute.size()) {
     Future<YourCallableImplementor> resultFuture = completionService.take(); 
     YourCallableImplementor result = resultFuture.get();
     received++; 
  }
} finally {
  service.shutdown();
}

في فئة وقت التشغيل ، هناك طريقة تسمى AvailableProcessors (). يمكنك استخدام ذلك لمعرفة عدد وحدات المعالجة المركزية لديك. نظرًا لأن برنامجك ملزم وحدة المعالجة المركزية ، فمن المحتمل أنك ترغب في الحصول على (على الأكثر) مؤشر ترابط واحد لكل وحدة المعالجة المركزية المتاحة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top