رشته های مجازی مسئولیت تخصیص منابع سیستم را از کد برنامه شما و به JVM بر عهده می گیرند. در اینجا اولین نگاهی به موضوعات مجازی در جاوا ۲۱ است.
- نحوه کار کردن رشتههای مجازی
- استفاده از رشتههای مجازی جاوا: یک نسخه آزمایشی
- دو روش برای استفاده از رشتههای مجازی
- بهترین روشها برای رشتههای مجازی
- بازسازی با رشتههای مجازی
- نتیجهگیری
یکی از گستردهترین بهروزرسانیهای جاوا ۱۹، معرفی رشتههای مجازی بود. رشتههای مجازی بخشی از Project Loom هستند و به طور رسمی بخشی از JVM از جاوا ۲۰ هستند.
نحوه کارکرد رشته های مجازی
رشته های مجازی یک لایه انتزاعی را بین فرآیندهای سیستم عامل و همزمانی در سطح برنامه معرفی می کنند. به عبارت دیگر، رشتههای مجازی را میتوان برای برنامهریزی وظایفی که ماشین مجازی جاوا هماهنگ میکند استفاده کرد، بنابراین JVM بین سیستم عامل و برنامه واسطه میشود. شکل ۱ معماری رشته های مجازی را نشان می دهد.
شکل ۱. معماری رشتههای مجازی در جاوا.
در این معماری، برنامه رشتههای مجازی را نمونهسازی میکند و JVM منابع محاسباتی را برای مدیریت آنها اختصاص میدهد. این را با رشتههای معمولی مقایسه کنید، که مستقیماً روی فرآیندهای سیستم عامل (OS) نگاشت میشوند. با موضوعات معمولی، کد برنامه مسئول تهیه و توزیع منابع سیستم عامل است. با رشته های مجازی، برنامه موضوعات مجازی را نمونه سازی می کند و بنابراین نیاز به همزمانی را بیان می کند. اما این JVM است که منابع را از سیستم عامل دریافت و آزاد می کند.
رشتههای مجازی در جاوا مشابه گوروتینها در Go language. هنگام استفاده از رشتههای مجازی، JVM تنها زمانی میتواند منابع محاسباتی را تخصیص دهد که رشتههای مجازی برنامه پارک شده باشند، به این معنی که آنها بیکار هستند و در انتظار کار جدید هستند. این غیرفعال شدن در اکثر سرورها رایج است: آنها یک رشته را به یک درخواست اختصاص میدهند و سپس آن را بیحرکت میکنند و منتظر یک رویداد جدید مانند پاسخ از یک ذخیرهگاه داده یا ورودی بیشتر از شبکه هستند.
به نوعی، رشته مجازی شکل پیچیده ای از ترکیب نخ است.
با استفاده از رشتههای جاوای معمولی، زمانی که یک سرور در یک درخواست در حالت غیرفعال بود، یک رشته سیستم عامل نیز بیحرکت بود، که مقیاس پذیری سرورها را به شدت محدود میکرد. همانطور که نیکولای پارلوگ توضیح داده است، “سیستم های عامل نمیتواند کارایی رشتههای پلتفرم را افزایش دهد، اما JDK با قطع رابطه یک به یک بین رشتههای خود و رشتههای سیستمعامل، بهتر از آنها استفاده خواهد کرد.”
تلاشهای قبلی برای کاهش مشکلات عملکرد و مقیاسپذیری مرتبط با رشتههای معمولی جاوا شامل کتابخانههای غیرهمزمان و واکنشی مانند JavaRX رشتههای مجازی از این جهت متفاوت هستند که در سطح JVM پیادهسازی میشوند، و در عین حال در ساختارهای برنامهنویسی موجود در جاوا قرار میگیرند. APIهای معمولی، مانند Executor
، میتوانند با رشتههای مجازی استفاده شوند.
استفاده از رشته های مجازی جاوا: نسخه آزمایشی
برای این نمایش، من یک برنامه جاوا ساده با کهن الگوی Maven< ایجاد کرده ام. /a>.
فهرست ۱ تغییراتی را که من در فایل POM کهن الگوی Maven ایجاد کردهام نشان میدهد، کامپایلر را برای استفاده از جاوا ۲۱ تنظیم میکند و mainClass
را مشخص میکند.
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
// ...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<mainClass>com.infoworld.App</mainClass>
</configuration>
</plugin>
</plugins>
//...
</build>
مطمئن شوید که JVM با حداقل جاوا ۲۱ در دسترس است! (اگر جاوا ۱۹ را اجرا می کنید، می توانید رشته های مجازی را با --preview-enabled=true
اجرا کنید.)
اکنون، میتوانید برنامه (و مثالهای زیر) را با mvn compile exec:java
اجرا کنید و ویژگیهای رشته مجازی کامپایل و اجرا میشوند.
دو روش برای استفاده از رشته های مجازی
حالا اجازه دهید دو روش اصلی استفاده از رشته های مجازی در کد خود را در نظر بگیریم. در حالی که رشتههای مجازی تغییر چشمگیری در نحوه عملکرد JVM ایجاد میکنند، کد در واقع بسیار شبیه به رشتههای جاوای معمولی است. این شباهت در طراحی است و بازسازی برنامه ها و سرورهای موجود را نسبتاً آسان می کند. این سازگاری همچنین به این معنی است که ابزارهای موجود برای نظارت و مشاهده رشتهها در JVM با رشتههای مجازی کار خواهند کرد.
Thread.startVirtualThread(Runnable r)
اصلی ترین راه برای استفاده از یک رشته مجازی با Thread.startVirtualThread(Runnable r)
است. این جایگزینی برای نمونه سازی یک رشته و فراخوانی thread.start()
است. کد نمونه را در فهرست ۲ در نظر بگیرید.
package com.infoworld;
import java.util.Random;
public class App {
public static void main( String[] args ) {
boolean vThreads = args.length > 0;
System.out.println( "Using vThreads: " + vThreads);
long start = System.currentTimeMillis();
Random random = new Random();
Runnable runnable = () -> { double i = random.nextDouble(1000) % random.nextDouble(1000); };
for (int i = 0; i < 50000; i++){
if (vThreads){
Thread.startVirtualThread(runnable);
} else {
Thread t = new Thread(runnable);
t.start();
}
}
long finish = System.currentTimeMillis();
long timeElapsed = finish - start;
System.out.println("Run time: " + timeElapsed);
}
}
هنگامی که با آرگومان اجرا می شود، کد موجود در فهرست ۲ از یک رشته مجازی استفاده می کند. در غیر این صورت از نخ های معمولی استفاده می کند. این به ما امکان می دهد تفاوت را به راحتی مشاهده کنیم. این برنامه ۵۰ هزار تکرار از هر نوع رشته ای را که انتخاب می کنید ایجاد می کند. سپس، مقداری ریاضی ساده با اعداد تصادفی انجام می دهد و مدت زمان اجرا را پیگیری می کند.
برای اجرای کد با رشتههای مجازی، تایپ کنید: mvn compile exec:java -Dexec.args="true"
. برای اجرا با رشته های استاندارد، تایپ کنید: mvn compile exec:java
. من یک تست عملکرد سریع انجام دادم و نتایج زیر را دریافت کردم:
- با رشته های مجازی: زمان اجرا: ۱۷۴
- با رشته های معمولی: زمان اجرا: ۵۴۵۰
این نتایج غیرعلمی هستند، اما تفاوت در زمان اجرا قابل توجه است. تجربه در خط فرمان شگفتانگیز است، زیرا نسخه vThread
تقریباً بلافاصله تکمیل میشود. شما واقعاً باید آن را امتحان کنید.
روش های دیگری نیز برای استفاده از Thread
برای ایجاد رشته های مجازی وجود دارد، مانند Thread.ofVirtual().start(runnable)
. برای اطلاعات بیشتر به اسناد موضوعات جاوا مراجعه کنید.
استفاده از یک اجرا کننده
راه اصلی دیگر برای شروع یک رشته مجازی با یک اجرا کننده است. مجریها در برخورد با رشتهها رایج هستند و روشی استاندارد برای هماهنگ کردن بسیاری از کارها و ادغام رشتهها ارائه میدهند.
ادغام با موضوعات مجازی لازم نیست زیرا ایجاد و دفع آنها ارزان است و بنابراین ادغام غیرضروری است. در عوض، می توانید JVM را به عنوان مدیریت thread pool برای شما در نظر بگیرید. با این حال، بسیاری از برنامهها از اجراکنندهها استفاده میکنند، بنابراین جاوا ۱۹ یک روش پیشنمایش جدید را در مجریها برای آسانتر کردن بازآفرینی به رشتههای مجازی ارائه میکند. لیست ۳ روش جدید را در کنار روش قدیمی به شما نشان می دهد.
// New method:
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
// Old method:
ExecutorService executor = Executors.newFixedThreadPool(Integer poolSize);
علاوه بر این، جاوا ۱۹ متد Executors.newThreadPerTaskExecutor(ThreadFactory threadFactory)
را معرفی کرد که می تواند یک ThreadFactory که رشته های مجازی می سازد. چنین کارخانه ای را می توان با Thread.ofVirtual().factory()
بدست آورد.
اطلاعات بیشتر در مورد روش های اجرایی
برای اطلاعات بیشتر در مورد روشهای اجرایی، مستندات اجرایی را ببینید .
بهترین روشها برای رشتههای مجازی
به طور کلی، از آنجا که رشتههای مجازی کلاس Thread
را پیادهسازی میکنند، میتوانند در هر جایی که یک رشته استاندارد باشد، استفاده شوند. با این حال، تفاوت هایی در نحوه استفاده از رشته های مجازی باید برای بهترین اثر وجود دارد. یک مثال استفاده از سمافورها برای کنترل تعداد رشتهها هنگام دسترسی به منبعی مانند ذخیرهگاه داده، به جای استفاده از یک مخزن نخ با محدودیت است. به ورود به جاوا ۱۹: رشتههای مجازی و رشتههای پلتفرم a> برای نکات بیشتر.
نکته مهم دیگر این است که رشتههای مجازی همیشه رشتههای شبح هستند، به این معنی که فرآیند JVM حاوی تا زمانی که کامل شوند زنده نگه میدارند. همچنین، شما نمی توانید اولویت آنها را تغییر دهید. روشهای تغییر اولویت و وضعیت شبح، بدون عملیات هستند. به اسناد موضوعات برای اطلاعات بیشتر در مورد این.
باز هم، به طور کلی، این اخطارها رسیدگی به موضوعات مجازی را برای توسعه دهنده آسان تر می کند. بیشتر کار بر روی پلت فرم فشار داده می شود. پلت فرم مخزن نخ است.
بازسازی با رشته های مجازی
رشتههای مجازی تغییر بزرگی هستند، اما بهطور عمدی به راحتی میتوان آنها را در یک پایگاه کد موجود اعمال کرد. رشتههای مجازی بیشترین و فوریترین تأثیر را روی سرورهایی مانند Tomcat و GlassFish چنین سرورهایی باید بتوانند رشته های مجازی را با کمترین تلاش انجام دهند. این به طور موثر برای کاربران نهایی سرور شفاف خواهد بود. برنامههایی که روی این سرورها اجرا میشوند، بدون هیچ تغییری در کد، دستاوردهای مقیاسپذیری را خالص خواهند کرد، که میتواند پیامدهای بسیار زیادی برای برنامههای کاربردی در مقیاس بزرگ داشته باشد. یک برنامه جاوا را در نظر بگیرید که روی بسیاری از سرورها و هسته ها اجرا می شود. به طور ناگهانی، میتواند درخواستهای همزمان بیشتری را رسیدگی کند (اگرچه، البته، همه چیز به نمایه رسیدگی به درخواست بستگی دارد).
سرورهای مانند Tomcat از قبل به رشته های مجازی اجازه داده شده است. اگر در مورد سرورها و موضوعات مجازی کنجکاو هستید، این پست وبلاگ توسط Cay Horstmann را در نظر بگیرید. a>، جایی که او روند پیکربندی Tomcat را برای رشته های مجازی نشان می دهد. او ویژگیهای پیشنمایش رشتههای مجازی را فعال میکند و Executor
را با یک پیادهسازی سفارشی جایگزین میکند که تنها با یک خط تفاوت دارد (شما حدس زدید، Executors.newThreadPerTaskExecutor)
. مزیت مقیاس پذیری قابل توجه است، زیرا او می گوید: “با این تغییر، ۲۰۰ درخواست ۳ ثانیه طول می کشد، و Tomcat به راحتی می تواند ۱۰۰۰۰ درخواست را بپذیرد.”
نتیجه گیری
رشته های مجازی یک تغییر عمده در JVM هستند. برای برنامه نویسان برنامه، آنها جایگزینی برای کدنویسی به سبک ناهمزمان با استفاده از تکنیک هایی مانند callback یا آتی هستند. در مجموع، میتوانیم رشتههای مجازی را بهعنوان یک آونگ ببینیم که به سمت یک الگوی برنامهنویسی همزمان در جاوا حرکت میکند، وقتی که با همزمانی سروکار داریم. این تقریباً در سبک برنامهنویسی (اگرچه در اجرا اصلاً نیست) با معرفی async/await توسط جاوا اسکریپت مشابه است. به طور خلاصه، نوشتن رفتار ناهمزمان صحیح با نحو ساده همزمان بسیار آسان میشود – حداقل در برنامههایی که رشتهها زمان زیادی را در حالت بیحرکتی صرف میکنند.
منابع زیر را برای کسب اطلاعات بیشتر در مورد رشته های مجازی بررسی کنید:
- رشته های مجازی: پایه های جدید برای برنامه های کاربردی جاوا در مقیاس بالا li>
- نحوه استفاده از رشته های مجازی جاوا ۱۹
- The Happy Coders معرفی رشته های مجازی در جاوا
- یک نحوه معرفی رشتههای مجازی جاوا در Project Loom li>
- معرفی ویدیویی برای Project Loom در اکوسیستم جاوا
- پست وبلاگ کی هورستمن در مهاجرت تامکت به رشته های مجازی li>
پست های مرتبط
مقدمه ای بر موضوعات مجازی: رویکردی جدید به همزمانی جاوا
مقدمه ای بر موضوعات مجازی: رویکردی جدید به همزمانی جاوا
مقدمه ای بر موضوعات مجازی: رویکردی جدید به همزمانی جاوا