مشکلاتی که multithreading در جاوا حل می کند
در اصل، چند رشته ای جاوا برای حل دو مشکل اصلی اختراع شد:-
چندین عمل را همزمان انجام دهید.
در مثال بالا، رشته های مختلف (یعنی اعضای خانواده) چندین عمل را به طور موازی انجام دادند: ظرف ها را شستند، به فروشگاه رفتند، چیزها را تا کردند.
یک مثال "برنامه نویس" بیشتر می توان ارائه داد. تصور کنید که یک برنامه با رابط کاربری دارید. هنگامی که دکمه Continue کلیک می شود، برخی از محاسبات باید در داخل برنامه انجام شود و کاربر باید صفحه رابط زیر را ببیند. اگر این اقدامات به صورت متوالی انجام شود، پس از کلیک بر روی دکمه "ادامه"، برنامه به سادگی مسدود می شود. کاربر همان صفحه را با دکمه "ادامه" می بیند تا زمانی که تمام محاسبات داخلی کامل شود و برنامه به قسمتی برسد که رابط شروع به ترسیم می کند.
خوب، چند دقیقه صبر کنیم!
ما همچنین می توانیم برنامه خود را بازسازی کنیم، یا، به قول برنامه نویسان، "موازی سازی". اجازه دهید محاسبات لازم در یک رشته و رندر رابط در رشته دیگر انجام شود. اکثر کامپیوترها منابع کافی برای این کار دارند. در این حالت ، برنامه "احمقانه" نخواهد بود و کاربر با آرامش بین صفحه های رابط حرکت می کند بدون اینکه نگران آنچه در داخل می افتد باشد. دخالت نمیکنه :)
-
سرعت دادن به محاسبات
همه چیز در اینجا بسیار ساده تر است. اگر پردازنده ما چندین هسته داشته باشد و اکثر پردازنده ها اکنون چند هسته ای هستند، لیست وظایف ما به صورت موازی توسط چندین هسته قابل حل است. بدیهی است که اگر نیاز به حل 1000 مشکل داشته باشیم و هر یک از آنها در یک ثانیه حل شود، یک هسته در 1000 ثانیه، دو هسته در 500 ثانیه، سه هسته در کمی بیش از 333 ثانیه و غیره با لیست کنار می آید.
Thread
. یعنی برای ایجاد و اجرای 10 Thread به 10 آبجکت از این کلاس نیاز دارید. بیایید ساده ترین مثال را بنویسیم:
public class MyFirstThread extends Thread {
@Override
public void run() {
System.out.println("I'm Thread! My name is " + getName());
}
}
برای ایجاد و راه اندازی رشته ها، باید یک کلاس ایجاد کنیم و آن را از java.lang
. Thread
و روش را در آن نادیده بگیرید run()
. مورد آخر بسیار مهم است. در متد است که run()
منطقی را که موضوع ما باید اجرا کند را تجویز می کنیم. حال، اگر یک نمونه بسازیم MyFirstThread
و آن را اجرا کنیم، متد run()
خطی را با نام آن در کنسول چاپ میکند: متد getName()
نام «سیستم» رشته را چاپ میکند که به طور خودکار اختصاص داده میشود. اگرچه، در واقع، چرا "اگر"؟ بیایید ایجاد کنیم و آزمایش کنیم!
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.start();
}
}
}
خروجی کنسول: I'm Thread! نام من Thread-2 است I'm Thread! نام من Thread-1 است I'm Thread! نام من Thread-0 است من موضوع هستم! نام من Thread-3 است I'm Thread! نام من Thread-6 است I'm Thread! نام من Thread-7 است I'm Thread! نام من Thread-4 است I'm Thread! نام من Thread-5 است I'm Thread! نام من Thread-9 است I'm Thread! نام من Thread-8 است ما 10 رشته (ابجکت) را ایجاد می کنیم MyFirstThread
که از Thread
آنها به ارث می رسد و با فراخوانی متد شی راه اندازی می کنیم start()
. پس از فراخوانی یک متد ، start()
متد آن شروع به کار می کند run()
و منطقی که در آن نوشته شده بود اجرا می شود. لطفا توجه داشته باشید: نام تاپیک ها به ترتیب نیست. خیلی عجیب است، چرا آنها به نوبت اعدام نشدند: Thread-0
، Thread-1
، Thread-2
و غیره؟ این دقیقاً نمونه ای از زمانی است که تفکر استاندارد و «متوالی» کارساز نخواهد بود. واقعیت این است که در این حالت ما فقط دستور ایجاد و راه اندازی 10 رشته را صادر می کنیم. به چه ترتیبی باید راهاندازی شوند، توسط زمانبندی رشته تصمیم میگیرد: مکانیزم ویژه در داخل سیستم عامل. اینکه دقیقاً چگونه ساختار یافته است و بر اساس چه اصولی تصمیم می گیرد، موضوع بسیار پیچیده ای است و اکنون به آن نمی پردازیم. نکته اصلی که باید به خاطر داشته باشید این است که برنامه نویس نمی تواند توالی اجرای thread را کنترل کند. برای درک جدی بودن وضعیت، روش را main()
از مثال بالا چند بار دیگر اجرا کنید. خروجی کنسول دوم: I'm Thread! نام من Thread-0 است من موضوع هستم! نام من Thread-4 است I'm Thread! نام من Thread-3 است I'm Thread! نام من Thread-2 است I'm Thread! نام من Thread-1 است I'm Thread! نام من Thread-5 است I'm Thread! نام من Thread-6 است I'm Thread! نام من Thread-8 است I'm Thread! نام من Thread-9 است I'm Thread! نام من Thread-7 خروجی کنسول سوم است: من Thread هستم! نام من Thread-0 است من موضوع هستم! نام من Thread-3 است I'm Thread! نام من Thread-1 است I'm Thread! نام من Thread-2 است I'm Thread! نام من Thread-6 است I'm Thread! نام من Thread-4 است I'm Thread! نام من Thread-9 است I'm Thread! نام من Thread-5 است I'm Thread! نام من Thread-7 است I'm Thread! نام من Thread-8 است
مشکلاتی که چند رشته ای ایجاد می کند
در مثال کتاب مشاهده کردید که multithreading مشکلات بسیار مهمی را حل می کند و استفاده از آن سرعت کار برنامه های ما را افزایش می دهد. در بسیاری از موارد - بارها. اما بی جهت نیست که چند رشته ای موضوعی پیچیده در نظر گرفته می شود. به هر حال، اگر به طور نادرست استفاده شود، به جای حل آنها، مشکلاتی ایجاد می کند. وقتی میگویم «مشکلات ایجاد کن»، منظورم چیزی انتزاعی نیست. دو مشکل خاص وجود دارد که multithreading می تواند ایجاد کند: بن بست و شرایط مسابقه. بن بست وضعیتی است که در آن موضوعات متعددی منتظر منابعی هستند که توسط یکدیگر اشغال شده اند و هیچ یک از آنها نمی توانند به اجرا ادامه دهند. در سخنرانی های آینده بیشتر در مورد آن صحبت خواهیم کرد، اما در حال حاضر این مثال کافی است: تصور کنید که thread-1 با مقداری Object-1 کار می کند، و Thread-2 با Object-2 کار می کند. برنامه به این صورت نوشته شده است:- Thread-1 کار با Object-1 را متوقف می کند و به محض اینکه Thread-2 کار با Object 2 را متوقف می کند و به Object-1 تغییر می کند به Object-2 می رود.
- Thread-2 کار با Object-2 را متوقف می کند و به محض اینکه Thread-1 کار با Object 1 را متوقف می کند و به Object-2 تغییر می کند به Object-1 می رود.
public class MyFirstThread extends Thread {
@Override
public void run() {
System.out.println("Выполнен поток " + getName());
}
}
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.start();
}
}
}
حال تصور کنید که این برنامه وظیفه عملکرد رباتی را بر عهده دارد که غذا را تهیه می کند! Thread-0 تخم مرغ ها را از یخچال خارج می کند. Stream 1 اجاق گاز را روشن می کند. Stream-2 یک ماهیتابه را بیرون می آورد و روی اجاق می گذارد. جریان 3 روی اجاق گاز آتش روشن می کند. استریم 4 داخل تابه روغن بریزید. استریم 5 تخم مرغ ها را می شکند و در ماهیتابه می ریزیم. جریان 6 پوسته ها را به سطل زباله می اندازد. Stream-7 تخم مرغ های همزده تمام شده را از روی حرارت برمی دارد. Potok-8 تخم مرغ های همزده را در بشقاب قرار می دهد. Stream 9 ظرف ها را می شست. به نتایج برنامه ما نگاه کنید: Thread-0 executed Thread-2 Thread-1 Thread executed Thread-4 Thread executed Thread-9 Thread executed Thread-5 Thread executed Thread-8 Thread executed Thread-7 Thread executed thread executed -3 Thread-6 thread اجرا شد آیا اسکریپت سرگرم کننده است؟ :) و همه اینها به این دلیل است که عملکرد برنامه ما به ترتیب اجرای نخ ها بستگی دارد. با کوچکترین تخطی از ترتیب، آشپزخانه ما تبدیل به جهنم می شود و رباتی که دیوانه شده است، همه چیز اطراف خود را نابود می کند. این نیز یک مشکل رایج در برنامه نویسی چند رشته ای است که بیش از یک بار در مورد آن خواهید شنید. در پایان سخنرانی، من می خواهم به شما یک کتاب در مورد چند رشته ای توصیه کنم.
GO TO FULL VERSION