JavaRush /وبلاگ جاوا /Random-FA /Multithreading در جاوا: ماهیت، مزایا و مشکلات رایج

Multithreading در جاوا: ماهیت، مزایا و مشکلات رایج

در گروه منتشر شد
سلام! اول از همه به شما تبریک می گویم: شما به مبحث Multithreading در جاوا رسیده اید! این یک دستاورد جدی است، راه طولانی در پیش است. اما آماده باشید: این یکی از دشوارترین مباحث دوره است. و نکته این نیست که کلاس های پیچیده یا روش های زیادی در اینجا استفاده می شود: برعکس، حتی دو دوجین هم وجود ندارد. بیشتر از این است که باید کمی تفکر خود را تغییر دهید. قبلا برنامه های شما به صورت متوالی اجرا می شد. برخی از خطوط کد از خطوط دیگر پیروی می کردند، برخی از روش ها از برخی دیگر پیروی می کردند و در کل همه چیز واضح بود. ابتدا چیزی را محاسبه کنید، سپس نتیجه را روی کنسول نمایش دهید، سپس برنامه را خاتمه دهید. برای درک چند رشته ای، بهتر است بر حسب همزمانی فکر کنید. بیایید با یک چیز بسیار ساده شروع کنیم :) Multithreading در جاوا: ماهیت، مزایا و مشکلات رایج - 1تصور کنید که خانواده شما از یک خانه به خانه دیگر نقل مکان می کنند. بخش مهمی از جابجایی، بسته بندی کتاب هایتان است. شما کتاب های زیادی جمع کرده اید و باید آنها را در جعبه ها قرار دهید. اکنون فقط شما آزاد هستید. مامان در حال آماده کردن غذا، برادر در حال جمع کردن لباس، و خواهر به فروشگاه رفته است. به تنهایی می توانید حداقل مدیریت کنید و دیر یا زود حتی خودتان این کار را انجام خواهید داد، اما زمان زیادی می برد. با این حال، 20 دقیقه دیگر خواهرت از فروشگاه برمی‌گردد و کار دیگری ندارد. بنابراین او می تواند به شما ملحق شود. وظیفه همان باقی ماند: کتاب ها را در جعبه ها قرار دهید. فقط دو برابر سریعتر اجرا می شود. چرا؟ چون کار به صورت موازی انجام می شود. دو "رشته" متفاوت (شما و خواهرتان) به طور همزمان یک کار را انجام می دهند و اگر چیزی تغییر نکند، تفاوت زمانی در مقایسه با موقعیتی که در آن همه کارها را به تنهایی انجام می دهید بسیار زیاد خواهد بود. اگر برادرتان به زودی وظیفه خود را به پایان برساند، می تواند به شما کمک کند و همه چیز سریعتر پیش خواهد رفت.

مشکلاتی که multithreading در جاوا حل می کند

در اصل، چند رشته ای جاوا برای حل دو مشکل اصلی اختراع شد:
  1. چندین عمل را همزمان انجام دهید.

    در مثال بالا، رشته های مختلف (یعنی اعضای خانواده) چندین عمل را به طور موازی انجام دادند: ظرف ها را شستند، به فروشگاه رفتند، چیزها را تا کردند.

    یک مثال "برنامه نویس" بیشتر می توان ارائه داد. تصور کنید که یک برنامه با رابط کاربری دارید. هنگامی که دکمه Continue کلیک می شود، برخی از محاسبات باید در داخل برنامه انجام شود و کاربر باید صفحه رابط زیر را ببیند. اگر این اقدامات به صورت متوالی انجام شود، پس از کلیک بر روی دکمه "ادامه"، برنامه به سادگی مسدود می شود. کاربر همان صفحه را با دکمه "ادامه" می بیند تا زمانی که تمام محاسبات داخلی کامل شود و برنامه به قسمتی برسد که رابط شروع به ترسیم می کند.

    خوب، چند دقیقه صبر کنیم!

    Multithreading در جاوا: ماهیت، مزایا و مشکلات رایج - 3

    ما همچنین می توانیم برنامه خود را بازسازی کنیم، یا، به قول برنامه نویسان، "موازی سازی". اجازه دهید محاسبات لازم در یک رشته و رندر رابط در رشته دیگر انجام شود. اکثر کامپیوترها منابع کافی برای این کار دارند. در این حالت ، برنامه "احمقانه" نخواهد بود و کاربر با آرامش بین صفحه های رابط حرکت می کند بدون اینکه نگران آنچه در داخل می افتد باشد. دخالت نمیکنه :)

  2. سرعت دادن به محاسبات

    همه چیز در اینجا بسیار ساده تر است. اگر پردازنده ما چندین هسته داشته باشد و اکثر پردازنده ها اکنون چند هسته ای هستند، لیست وظایف ما به صورت موازی توسط چندین هسته قابل حل است. بدیهی است که اگر نیاز به حل 1000 مشکل داشته باشیم و هر یک از آنها در یک ثانیه حل شود، یک هسته در 1000 ثانیه، دو هسته در 500 ثانیه، سه هسته در کمی بیش از 333 ثانیه و غیره با لیست کنار می آید.

اما، همانطور که قبلاً در این سخنرانی خواندید، سیستم‌های مدرن بسیار هوشمند هستند و حتی در یک هسته محاسباتی می‌توانند موازی‌سازی یا شبه موازی‌سازی را زمانی که وظایف به طور متناوب انجام می‌شوند، پیاده‌سازی کنند. بیایید از موارد عمومی به موارد خاص برویم و با کلاس اصلی کتابخانه جاوا مربوط به multithreading - java.lang.Thread آشنا شویم. به عبارت دقیق تر، رشته ها در جاوا با نمونه هایی از کلاس نمایش داده می شوند 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 می تواند ایجاد کند: بن بست و شرایط مسابقه. بن بست وضعیتی است که در آن موضوعات متعددی منتظر منابعی هستند که توسط یکدیگر اشغال شده اند و هیچ یک از آنها نمی توانند به اجرا ادامه دهند. در سخنرانی های آینده بیشتر در مورد آن صحبت خواهیم کرد، اما در حال حاضر این مثال کافی است: Multithreading در جاوا: ماهیت، مزایا و مشکلات رایج - 4 تصور کنید که thread-1 با مقداری Object-1 کار می کند، و Thread-2 با Object-2 کار می کند. برنامه به این صورت نوشته شده است:
  1. Thread-1 کار با Object-1 را متوقف می کند و به محض اینکه Thread-2 کار با Object 2 را متوقف می کند و به Object-1 تغییر می کند به Object-2 می رود.
  2. Thread-2 کار با Object-2 را متوقف می کند و به محض اینکه Thread-1 کار با Object 1 را متوقف می کند و به Object-2 تغییر می کند به Object-1 می رود.
حتی بدون دانش عمیق از چند رشته ای، به راحتی می توانید درک کنید که هیچ کاری از آن حاصل نخواهد شد. نخ ها هرگز جای خود را عوض نمی کنند و برای همیشه منتظر یکدیگر می مانند. به نظر می رسد خطا آشکار است، اما در واقعیت اینطور نیست. شما به راحتی می توانید آن را به برنامه اجازه دهید. نمونه‌هایی از کدهایی که باعث بن‌بست می‌شوند را در سخنرانی‌های بعدی بررسی خواهیم کرد. به هر حال، Quora یک مثال عالی در زندگی واقعی دارد که توضیح می دهد بن بست چیست . «در برخی از ایالت‌های هند، زمین‌های کشاورزی را به شما نمی‌فروشند مگر اینکه به‌عنوان کشاورز ثبت‌نام کنید. اما اگر زمین کشاورزی نداشته باشید، به عنوان کشاورز ثبت نام نمی کنید.» عالی چی بگم :) حالا در مورد شرایط مسابقه - وضعیت مسابقه. Multithreading در جاوا: ماهیت، مزایا و مشکلات رایج - 5شرط مسابقه یک نقص طراحی در یک سیستم یا برنامه چند رشته ای است که در آن عملکرد سیستم یا برنامه به ترتیب اجرای بخش هایی از کد بستگی دارد. مثال در حال اجرا را به خاطر بسپارید:
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 اجرا شد آیا اسکریپت سرگرم کننده است؟ :) و همه اینها به این دلیل است که عملکرد برنامه ما به ترتیب اجرای نخ ها بستگی دارد. با کوچکترین تخطی از ترتیب، آشپزخانه ما تبدیل به جهنم می شود و رباتی که دیوانه شده است، همه چیز اطراف خود را نابود می کند. این نیز یک مشکل رایج در برنامه نویسی چند رشته ای است که بیش از یک بار در مورد آن خواهید شنید. در پایان سخنرانی، من می خواهم به شما یک کتاب در مورد چند رشته ای توصیه کنم.
Multithreading در جاوا: ماهیت، جوانب مثبت و مشکلات رایج - 6
"جاوا همزمانی در عمل" در سال 2006 نوشته شد، اما ارتباط خود را از دست نداده است. این برنامه‌نویسی چند رشته‌ای در جاوا را پوشش می‌دهد، که از اصول اولیه شروع می‌شود و با فهرستی از رایج‌ترین خطاها و آنتی‌الگوها پایان می‌یابد. اگر تصمیم گرفتید که یک استاد برنامه نویسی چند رشته ای شوید، خواندن این کتاب ضروری است. شما را در سخنرانی های بعدی می بینم! :)
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION