إنشاء الخيوط الافتراضية
Thread.ofVirtual وexecutors
إنشاء الخيوط الافتراضية درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.
طرق إنشاء الخيوط الافتراضية
توفر Java عدة نقاط دخول لإنشاء الخيوط الافتراضية. وأهم نقطتين هما منشئ Thread.ofVirtual() ومصنع Executors.newVirtualThreadPerTaskExecutor().
يستعرض هذا الدرس كل طريقة منهما.
المنشئ: start
تعيد Thread.ofVirtual() منشئًا. ويؤدي استدعاء .start(runnable) إلى إنشاء الخيط وبدء تشغيله فورًا.
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = Thread.ofVirtual().start(() ->
System.out.println("Started directly"));
t.join();
}
}المنشئ: unstarted
استخدم .unstarted(runnable) عندما تريد إعداد الخيط وبدء تشغيله لاحقًا.
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = Thread.ofVirtual().unstarted(() ->
System.out.println("Started later"));
System.out.println("Before start, alive? " + t.isAlive());
t.start();
t.join();
}
}مصنع قابل لإعادة الاستخدام
يمكن للمنشئ إنتاج ThreadFactory عبر .factory(). ويؤدي كل استدعاء إلى newThread إلى إنشاء خيط افتراضي جديد.
import java.util.concurrent.ThreadFactory;
public class Main {
public static void main(String[] args) throws InterruptedException {
ThreadFactory factory = Thread.ofVirtual().name("job-", 0).factory();
Thread a = factory.newThread(() ->
System.out.println(Thread.currentThread().getName()));
Thread b = factory.newThread(() ->
System.out.println(Thread.currentThread().getName()));
a.start(); b.start();
a.join(); b.join();
}
}الطريقة الميسّرة
تُعد Thread.startVirtualThread(runnable) اختصارًا لإنشاء خيط افتراضي غير مُسمّى وبدء تشغيله في استدعاء واحد.
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = Thread.startVirtualThread(() ->
System.out.println("One-liner virtual thread"));
t.join();
}
}نهج Executor
في الشيفرة الموجّهة نحو المهام، يُفضَّل استخدام Executors.newVirtualThreadPerTaskExecutor(). فهو ينشئ خيطًا افتراضيًا جديدًا لكل مهمة مُرسَلة.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) {
exec.submit(() -> System.out.println("task one"));
exec.submit(() -> System.out.println("task two"));
}
System.out.println("All tasks submitted and completed");
}
}لماذا try-with-resources
منذ Java 19، تطبّق ExecutorService الواجهة AutoCloseable. ويؤدي إغلاقها داخل كتلة try-with-resources إلى الانتظار حتى اكتمال جميع المهام المُرسَلة.
يوفّر ذلك إيقاف تشغيل منظّمًا ونظيفًا، من دون استدعاءات shutdown وawaitTermination يدويًا.
إرسال مهام كثيرة
يتعامل المنفّذ المخصّص لكل مهمة بسهولة مع أعداد هائلة من المهام. ويحصل كلٌّ منها على خيط افتراضي خاص به.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
public static void main(String[] args) {
AtomicInteger sum = new AtomicInteger();
try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 1; i <= 1000; i++) {
final int n = i;
exec.submit(() -> sum.addAndGet(n));
}
}
System.out.println("Sum 1..1000 = " + sum.get());
}
}جمع النتائج باستخدام Future
يعيد submit كائنًا من نوع Future، لذا يمكنك جمع القيم المُعادة كما تفعل مع أي منفّذ آخر.
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws Exception {
try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) {
Future<Integer> f = exec.submit(() -> 6 * 7);
System.out.println("Result: " + f.get());
}
}
}المنشئ مقابل Executor
اختر بناءً على الغرض:
- Builder / startVirtualThread للخيوط التي تُنشأ لمرة واحدة أو عند الحاجة إلى تسمية مخصّصة
- newVirtualThreadPerTaskExecutor لإرسال مجموعات من المهام وجمع النتائج
تنشئ الطريقتان خيطًا افتراضيًا واحدًا لكل وحدة عمل، وهذا هو المطلوب تمامًا.
لا تُخزّن Executor افتراضيًا مؤقتًا
لا تُعِد استخدام منفّذ واحد للخيوط الافتراضية كما لو كان تجمّعًا ثابتًا من العاملين. لا مشكلة في إعادة استخدام المنفّذ نفسه، لكن تذكّر أن كل مهمة تنشئ خيطًا جديدًا تمامًا.
الفكرة هي أنه لا يوجد تجميع للخيوط، بل توجد فقط طريقة ميسّرة لإرسال المهام.
اختبار سريع
اختر أفضل طريقة لتشغيل مجموعة كبيرة من المهام، بحيث تعمل كل مهمة على خيط افتراضي خاص بها.
مراجعة
أصبحت تعرف الآن كيفية إنشاء الخيوط الافتراضية:
Thread.ofVirtual().start(...)و.unstarted(...)- الاستدعاء المختصر
Thread.startVirtualThread(...) .factory()لإنشاءThreadFactoryقابل لإعادة الاستخدامExecutors.newVirtualThreadPerTaskExecutor()مع try-with-resources
التالي: الاختيار بين خيوط المنصة والخيوط الافتراضية.
الأسئلة الشائعة
هل درس «إنشاء الخيوط الافتراضية» مجاني؟
نعم — نص درس «إنشاء الخيوط الافتراضية» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.
ماذا ستتعلم في «إنشاء الخيوط الافتراضية»؟
Thread.ofVirtual وexecutors تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟
لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «إنشاء الخيوط الافتراضية»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟
نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- ما الخيوط الافتراضية
- إنشاء الخيوط الافتراضية
- الخيوط المنصّية مقابل الافتراضية
- المزالق: التثبيت وThreadLocals