تعدد الخيوط في Java


يمكن لأي تطبيق أن يحتوي على عمليات متعددة (مثيلات). ويمكن تخصيص كل من هذه العمليات إما كخيط واحد أو خيوط متعددة. سنرى في هذا البرنامج التعليمي كيفية تنفيذ مهام متعددة في نفس الوقت، كما سنتعلم المزيد عن الخيوط والمزامنة بين الخيوط.

ما هو موضوع واحد؟

خيط واحد في Java هي في الأساس وحدة خفيفة الوزن وأصغر وحدة معالجة. Java يستخدم الخيوط باستخدام "فئة الخيوط". هناك نوعان من الخيوط - موضوع المستخدم والموضوع الخفي (يتم استخدام خيوط الديمون عندما نريد تنظيف التطبيق ويتم استخدامها في الخلفية). عند بدء تشغيل التطبيق لأول مرة، يتم إنشاء خيط المستخدم. بعد ذلك، يمكننا إنشاء العديد من خيوط المستخدم وخيوط الديمون.

مثال على موضوع واحد:

package demotest;

public class GuruThread
{
       public static void main(String[] args) {
              System.out.println("Single Thread");
       }
}

مزايا الخيط الواحد:

  • يقلل الحمل في التطبيق عند تنفيذ مؤشر ترابط واحد في النظام
  • كما أنه يقلل من تكلفة صيانة التطبيق.

ما هو تعدد في Java?

خاصية تعدد in Java هي عملية تنفيذ خيطين أو أكثر في وقت واحد لتحقيق أقصى استفادة من وحدة المعالجة المركزية. تنفذ التطبيقات متعددة الخيوط خيطين أو أكثر يتم تشغيلهما في وقت واحد. ومن ثم، تُعرف أيضًا باسم التزامن في Java. كل موضوع يعمل بالتوازي مع بعضها البعض. لا تقوم الخيوط المتعددة بتخصيص منطقة ذاكرة منفصلة، ​​وبالتالي فهي توفر الذاكرة. كما أن تبديل السياق بين سلاسل الرسائل يستغرق وقتًا أقل.

مثال على موضوع متعدد:

package demotest;
public class GuruThread1 implements Runnable
{
       public static void main(String[] args) {
        Thread guruThread1 = new Thread("Guru1");
        Thread guruThread2 = new Thread("Guru2");
        guruThread1.start();
        guruThread2.start();
        System.out.println("Thread names are following:");
        System.out.println(guruThread1.getName());
        System.out.println(guruThread2.getName());
    }
    @Override
    public void run() {
    }
}

مزايا الخيوط المتعددة:

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

دورة حياة الموضوع في Java

دورة حياة الخيط:

دورة حياة الموضوع في Java
دورة حياة الموضوع في Java

هناك مراحل مختلفة لدورة حياة الخيط كما هو موضح في الرسم البياني أعلاه:

  1. جديد
  2. قابل للجري
  3. الركض
  4. انتظار
  5. في ذمة الله تعالى
  1. جديد: في هذه المرحلة، يتم إنشاء الخيط باستخدام فئة "Thread class". ويبقى على هذه الحالة حتى البرنامج يبدأ الخيط. ومن المعروف أيضا باسم الخيط المولود.
  2. قابل للتشغيل: في هذه الصفحة، يتم استدعاء مثيل الموضوع باستخدام طريقة البدء. يتم منح التحكم في مؤشر الترابط إلى المجدول لإنهاء التنفيذ. يعتمد ذلك على المجدول، سواء كان سيتم تشغيل مؤشر الترابط.
  3. تشغيل: عندما يبدأ تنفيذ الخيط، تتغير الحالة إلى حالة "التشغيل". يقوم المجدول بتحديد مؤشر ترابط واحد من تجمع مؤشرات الترابط، ويبدأ التنفيذ في التطبيق.
  4. انتظار: هذه هي الحالة التي يتعين فيها على الخيط الانتظار. نظرًا لوجود خيوط متعددة تعمل في التطبيق، فهناك حاجة إلى المزامنة بين الخيوط. وبالتالي، يتعين على خيط واحد الانتظار حتى يتم تنفيذ الخيط الآخر. لذلك، يشار إلى هذه الحالة بحالة الانتظار.
  5. ميت: هذه هي الحالة عند إنهاء مؤشر الترابط. يكون مؤشر الترابط في حالة التشغيل وبمجرد الانتهاء من معالجته يصبح في "حالة ميتة".


طرق تعدد العمليات في Java

بعض الطرق الشائعة الاستخدام للخيوط هي:

خدمة التوصيل الوصف
بداية() تبدأ هذه الطريقة في تنفيذ الخيط و JVM يستدعي طريقة التشغيل () على الموضوع.
النوم (كثافة العمليات ميلي ثانية) هذه الطريقة تجعل الخيط في وضع السكون، وبالتالي يتوقف تنفيذ الخيط لمدة ميلي ثانية، وبعد ذلك يبدأ الخيط في التنفيذ مرة أخرى. وهذا يساعد في مزامنة الخيطين.
getName () يقوم بإرجاع اسم الموضوع.
setPriority(int newpriority) يغير أولوية الموضوع.
أَثْمَر () يؤدي إلى توقف مؤشر الترابط الحالي وتنفيذ سلاسل الرسائل الأخرى.

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

package demotest;
public class thread_example1 implements Runnable {
    @Override
    public void run() {
    }
    public static void main(String[] args) {
        Thread guruthread1 = new Thread();
        guruthread1.start();
        try {
            guruthread1.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        guruthread1.setPriority(1);
        int gurupriority = guruthread1.getPriority();
        System.out.println(gurupriority);
        System.out.println("Thread Running");
  }
}

شرح الكود:

  • سطر الكود 2: نحن نقوم بإنشاء فئة "thread_Example1" والتي تقوم بتنفيذ الواجهة القابلة للتشغيل (يجب تنفيذها بواسطة أي فئة من المفترض أن يتم تنفيذ مثيلاتها بواسطة مؤشر الترابط.)
  • سطر الكود 4: إنه يتجاوز طريقة التشغيل للواجهة القابلة للتشغيل حيث أنه من الضروري تجاوز هذه الطريقة
  • سطر الكود 6: لقد حددنا هنا الطريقة الرئيسية التي سنبدأ بها تنفيذ الخيط.
  • سطر الكود 7: نحن هنا نقوم بإنشاء اسم موضوع جديد باسم "guruthread1" عن طريق إنشاء فئة جديدة من المواضيع.
  • سطر الكود 8: سوف نستخدم طريقة "البدء" للخيط باستخدام مثيل "guruthread1". هنا سيبدأ تنفيذ الخيط.
  • سطر الكود 10: نحن هنا نستخدم طريقة "السكون" للخيط باستخدام مثيل "guruthread1". ومن ثم، سوف ينام الخيط لمدة 1000 مللي ثانية.
  • الكود 9-14: لقد وضعنا هنا طريقة السكون في كتلة محاولة الالتقاط حيث يوجد استثناء محدد والذي يحدث، أي استثناء متقطع.
  • سطر الكود 15: نحن هنا نضبط أولوية الخيط على 1 من أي أولوية كانت
  • سطر الكود 16: نحن هنا نحصل على أولوية الموضوع باستخدام getPriority()
  • سطر الكود 17: نحن هنا نقوم بطباعة القيمة التي تم جلبها من getPriority
  • سطر الكود 18: نحن هنا نكتب نصًا بأن الخيط قيد التشغيل.

عند تنفيذ الكود أعلاه، ستحصل على الناتج التالي:

مثال الموضوع في Java

الإخراج:

5 هي أولوية الموضوع، وتشغيل الموضوع هو النص الذي هو ناتج الكود الخاص بنا.

Java خيط Syncكرونة

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

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

ويمكن كتابتها بالشكل التالي:

Synchronized(object)
{  
        //Block of statements to be synchronized
}

تعدد الخيوط في Java برامج المثال

في هذا تعدد Java على سبيل المثال، سوف نأخذ خيطين ونحضر أسماء الخيط.

Example1:

GuruThread1.java
package demotest;
public class GuruThread1 implements Runnable{

    /**
     * @param args
     */
    public static void main(String[] args) {
        Thread guruThread1 = new Thread("Guru1");
        Thread guruThread2 = new Thread("Guru2");
        guruThread1.start();
        guruThread2.start();
        System.out.println("Thread names are following:");
        System.out.println(guruThread1.getName());
        System.out.println(guruThread2.getName());
    }
    @Override
    public void run() {
    }
}

شرح الكود:

  • سطر الكود 3: لقد اتخذنا فئة "GuruThread1" التي تنفذ Runnable (يجب تنفيذها بواسطة أي فئة تم تصميم مثيلاتها للتنفيذ بواسطة مؤشر الترابط.)
  • سطر الكود 8: هذه هي الطريقة الرئيسية للفئة
  • سطر الكود 9: نحن هنا نقوم بإنشاء مثيل لفئة Thread وإنشاء مثيل يسمى "guruThread1" وإنشاء سلسلة رسائل.
  • سطر الكود 10: نحن هنا نقوم بإنشاء مثيل لفئة Thread وإنشاء مثيل يسمى "guruThread2" وإنشاء سلسلة رسائل.
  • سطر الكود 11: لقد بدأنا الموضوع، أي guruThread1.
  • سطر الكود 12: لقد بدأنا الموضوع، أي guruThread2.
  • سطر الكود 13: إخراج النص على النحو التالي "أسماء المواضيع هي التالية:"
  • سطر الكود 14: الحصول على اسم مؤشر الترابط 1 باستخدام طريقة getName () لفئة مؤشر الترابط.
  • سطر الكود 15: الحصول على اسم مؤشر الترابط 2 باستخدام طريقة getName () لفئة مؤشر الترابط.

عند تنفيذ الكود أعلاه، ستحصل على الناتج التالي:

Java مثال تعدد الخيوط

الإخراج:

يتم إخراج أسماء المواضيع هنا كـ

  • Guru1
  • Guru2

مثال 2:

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

كما أننا نأخذ فصلين

  • واحد الذي سينفذ الواجهة القابلة للتشغيل و
  • طريقة أخرى سيكون لها الطريقة الرئيسية ويتم تنفيذها وفقًا لذلك.
package demotest;
public class GuruThread2 {
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  GuruThread3 threadguru1 = new GuruThread3("guru1");
  threadguru1.start();
  GuruThread3 threadguru2 = new GuruThread3("guru2");
  threadguru2.start();
 }
}
class GuruThread3 implements Runnable {
 Thread guruthread;
 private String guruname;
 GuruThread3(String name) {
  guruname = name;
 }
 @Override
 public void run() {
  System.out.println("Thread running" + guruname);
  for (int i = 0; i < 4; i++) {
   System.out.println(i);
   System.out.println(guruname);
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    System.out.println("Thread has been interrupted");
   }
  }
 }
 public void start() {
  System.out.println("Thread started");
  if (guruthread == null) {
   guruthread = new Thread(this, guruname);
   guruthread.start();
  }
 }
}

شرح الكود:

  • سطر الكود 2: نحن هنا نأخذ فصلًا دراسيًا "GuruThread2" والذي سيحتوي على الطريقة الرئيسية فيه.
  • سطر الكود 4: نحن هنا نتخذ الطريقة الرئيسية للفصل.
  • سطر الكود 6-7: نحن هنا نقوم بإنشاء مثيل للفئة GuruThread3 (الذي تم إنشاؤه في السطور التالية من الكود) باسم "threadguru1" ونبدأ الموضوع.
  • سطر الكود 8-9: نحن هنا نقوم بإنشاء مثيل آخر للفئة GuruThread3 (الذي تم إنشاؤه في السطور التالية من الكود) باسم "threadguru2" ونبدأ الموضوع.
  • سطر الكود 11: نحن هنا نقوم بإنشاء فئة "GuruThread3" التي تنفذ الواجهة القابلة للتشغيل (يجب تنفيذها بواسطة أي فئة تم تصميم مثيلاتها للتنفيذ بواسطة مؤشر الترابط.)
  • سطر الكود 13-14: نحن نأخذ متغيرين للفئة أحدهما من فئة الخيط والآخر من فئة السلسلة.
  • سطر الكود 15-18: نحن نتجاوز مُنشئ GuruThread3، الذي يأخذ وسيطة واحدة كنوع سلسلة (وهو اسم سلسلة الرسائل) الذي يتم تعيينه لمتغير الفئة guruname وبالتالي يتم تخزين اسم سلسلة الرسائل.
  • سطر الكود 20: نحن هنا نتجاوز طريقة التشغيل () للواجهة القابلة للتشغيل.
  • سطر الكود 21: نقوم بإخراج اسم الموضوع باستخدام بيان println.
  • سطر الكود 22-31: نحن هنا نستخدم حلقة for مع عداد تمت تهيئته إلى 0، ولا ينبغي أن يكون أقل من 4 (يمكننا أخذ أي رقم وبالتالي سيتم تشغيل الحلقة 4 مرات) وزيادة العداد. نحن نقوم بطباعة اسم مؤشر الترابط ونجعل مؤشر الترابط في وضع السكون لمدة 1000 مللي ثانية داخل كتلة محاولة الالتقاط حيث يتم رفع استثناء التحقق من طريقة السكون.
  • سطر الكود 33: نحن هنا نتجاوز طريقة البدء للواجهة القابلة للتشغيل.
  • سطر الكود 35: نقوم بإخراج النص "بدأ الموضوع".
  • سطر الكود 36-40: نحن هنا نأخذ شرط if للتحقق مما إذا كان guruthread لمتغير الفئة له قيمة أم لا. إذا كان فارغًا، فإننا نقوم بإنشاء مثيل باستخدام فئة مؤشر الترابط التي تأخذ الاسم كمعلمة (القيمة التي تم تعيينها لها في المُنشئ). وبعد ذلك يتم بدء تشغيل الخيط باستخدام طريقة start ().

عند تنفيذ الكود أعلاه، ستحصل على الناتج التالي:

مثال على تعدد مؤشرات الترابط في Java

الناتج:

هناك موضوعان، وبالتالي، نحصل على رسالة مرتين "بدأ الموضوع".

نحصل على أسماء الخيط كما أخرجناها.

يتم الدخول في حلقة for حيث نقوم بطباعة اسم العداد والخيط ويبدأ العداد بالرقم 0.

يتم تنفيذ الحلقة ثلاث مرات ويتم سكون الخيط بين الخيط لمدة 1000 مللي ثانية.

وبالتالي، أولاً، نحصل على guru1 ثم guru2 ثم مرة أخرى guru2 لأن الخيط ينام هنا لمدة 1000 مللي ثانية ثم guru1 التالي ومرة ​​أخرى guru1، ينام الخيط لمدة 1000 مللي ثانية، لذلك نحصل على guru2 ثم guru1.

الملخص

في هذا البرنامج التعليمي، رأينا تطبيقات متعددة الخيوط في Java وكيفية استخدام الخيط المفرد والمتعدد في Java.

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