JavaRush /وبلاگ جاوا /Random-FA /Multithreading: آنچه روش های کلاس Thread انجام می دهند

Multithreading: آنچه روش های کلاس Thread انجام می دهند

در گروه منتشر شد
سلام! امروز ما همچنان در مورد چند رشته ای صحبت می کنیم. بیایید نگاهی به کلاس Thread و نحوه کار چندین متد آن بیندازیم. قبلاً، وقتی متدهای کلاس را مطالعه می کردیم، اغلب آن را به سادگی اینگونه می نوشتیم: "نام متد" -> "آنچه انجام می دهد".
Multithreading: آنچه متدهای کلاس Thread انجام می دهند - 1
این با روش‌های Thread کار نمی‌کند :) منطق آنها پیچیده‌تر است و بدون چندین مثال قابل درک نیست.

متد Thread.start().

بیایید با تکرار شروع کنیم. همانطور که احتمالاً به خاطر دارید، می توانید با ارث بردن کلاس خود از کلاس Threadو لغو متد موجود در آن، یک رشته ایجاد کنید run(). اما، البته، به خودی خود شروع نخواهد شد. برای انجام این کار، متد را روی شیء خود فراخوانی می کنیم start(). Multithreading: آنچه متدهای کلاس Thread انجام می دهند - 2بیایید مثال سخنرانی قبلی را به خاطر بیاوریم:
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();
       }
   }
}
لطفا توجه داشته باشید: برای شروع یک موضوع، باید متد خاص را فراخوانی کنیدstart()، نهrun()! مرتکب این اشتباه آسان است، مخصوصاً زمانی که برای اولین بار چند رشته ای را یاد می گیرید. اگر در مثال ما متد شیء راrun()به جایstart()، نتیجه به این صورت خواهد بود:
public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
Thread-0 thread executed Thread-1 Thread executed Thread-2 Thread executed Thread-3 Thread executed Thread-4 Thread executed Thread-5 Thread executed Thread-6 Thread executed Thread-8thread executed Thread-3 خواندن اجرا شد به دنباله خروجی نگاه کنید: همه چیز کاملاً مرتب است. عجیبه، درسته؟ ما به این عادت نداریم، زیرا از قبل می‌دانیم که ترتیب راه‌اندازی و اجرای رشته‌ها توسط هوش فوق‌العاده درون سیستم عامل ما - زمان‌بندی رشته‌ها - تعیین می‌شود. شاید من فقط خوش شانس بودم؟ البته از شانس نیست. می توانید با اجرای برنامه چند بار دیگر این موضوع را تأیید کنید. نکته این است که فراخوانی مستقیم یک متدrun()هیچ ارتباطی با چند رشته ای ندارد. در این حالت، برنامه در رشته اصلی - رشته ای که متد در آن اجرا می شود - اجرا می شودmain(). به سادگی 10 خط را به صورت متوالی به کنسول خروجی می دهد و تمام. هیچ 10 موضوعی شروع نمی شود. بنابراین، برای آینده به یاد داشته باشید و دائما خود را بررسی کنید. اگه میخوای انجام بشهrun()زنگ بزنstart(). بیایید ادامه دهیم.

متد Thread.sleep().

برای توقف اجرای رشته فعلی برای مدتی، از sleep(). Multithreading: آنچه متدهای کلاس Thread انجام می دهند - 3این روش sleep()تعداد میلی‌ثانیه‌ها را به‌عنوان پارامتر می‌گیرد، یعنی زمانی که نخ باید در آن بخوابد.
public class Main {

   public static void main(String[] args) throws InterruptedException {

       long start = System.currentTimeMillis();

       Thread.sleep(3000);

       System.out.println(" - Сколько я проспал? \n - " + ((System.currentTimeMillis()-start)) / 1000 + " секунды");

   }
}
خروجی کنسول: - چقدر خوابیدم؟ - 3 ثانیه لطفا توجه داشته باشید: روش sleep()ثابت است: موضوع فعلی را به حالت خواب می برد. یعنی اونی که فعلا داره کار میکنه. نکته مهم دیگر: جریان در حالت خواب می تواند قطع شود. در این مورد، یک استثنا در برنامه رخ می دهد InterruptedException. در زیر به یک مثال نگاه خواهیم کرد. به هر حال، پس از "بیدار شدن" موضوع چه اتفاقی می افتد؟ آیا بلافاصله از همان جایی که متوقف شد به اجرای خود ادامه می دهد؟ خیر پس از بیدار شدن رشته - زمانی که زمان به عنوان آرگومان منقضی می شود Thread.sleep()- وارد حالت اجرا می شود . با این حال، این بدان معنا نیست که زمان‌بندی رشته آن را اجرا خواهد کرد. کاملاً ممکن است که به رشته‌های «غیر خواب» دیگر ترجیح دهد و رشته «تازه بیدار» ما کمی بعد به کار خود ادامه دهد. حتما به خاطر داشته باشید: "بیدار شدن به معنای ادامه کار در همان ثانیه نیست!"

روش () Thread.join

Многопоточность: что делают методы класса Thread - 4این روش join()اجرای thread فعلی را تا زمانی که رشته دیگری تکمیل شود به حالت تعلیق در می آورد. اگر 2 رشته داشته باشیم، t1و t2، و می نویسیم -
t1.join()
t2تا زمانی که t1 کار خود را کامل نکند شروع به کار نخواهد کرد. از این روش join()می توان برای اطمینان از توالی اجرای نخ ها استفاده کرد. بیایید join()با استفاده از یک مثال به کار نگاه کنیم:
public class ThreadExample extends Thread {

   @Override
   public void run() {

       System.out.println("Начало работы потока " + getName());

       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("Поток " + getName() +  " завершил работу.");
   }
}


public class Main {

   public static void main(String[] args) throws InterruptedException {

       ThreadExample t1 = new ThreadExample();
       ThreadExample t2 = new ThreadExample();

       t1.start();


 /*Второй поток t2 начнет выполнение только после того, How будет завершен
       (or бросит исключение) первый поток - t1*/
       try {
           t1.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       t2.start();

       //Главный поток продолжит работу только после того, How t1 и t2 завершат работу
       try {
           t1.join();
           t2.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println("Все потоки закончor работу, программа завершена");

   }
}
ما یک کلاس ساده ایجاد کرده ایم ThreadExample. وظیفه آن این است که پیامی را در مورد شروع کار روی صفحه نمایش دهد، سپس به مدت 5 ثانیه به خواب رفته و در پایان از اتمام کار اطلاع دهد. هیچ چیز پیچیده ای نیست. منطق اصلی در کلاس موجود است Main. به نظرات نگاه کنید: با استفاده از روش، join()ما با موفقیت دنباله اجرای موضوعات را کنترل می کنیم. اگر شروع تاپیک را به خاطر داشته باشید، زمانبندی رشته این کار را انجام داد. او آنها را به صلاحدید خود راه اندازی کرد: هر بار متفاوت. در اینجا، با استفاده از روش، اطمینان حاصل کردیم که ابتدا thread راه اندازی و اجرا می شود t1، سپس thread t2و تنها پس از آنها نخ اصلی اجرای برنامه. برو جلو. در برنامه‌های واقعی، اغلب با موقعیت‌هایی مواجه می‌شوید که نیاز به وقفه در اجرای برخی موضوعات دارید. به عنوان مثال، موضوع ما در حال اجرا است، اما منتظر یک رویداد یا شرایط خاص است. اگر این اتفاق بیفتد، متوقف می شود. شاید منطقی باشد اگر روشی مانند stop(). با این حال، همه چیز به این سادگی نیست. روزی روزگاری، متدی Thread.stop()در جاوا واقعا وجود داشت و به شما اجازه می داد کار یک رشته را قطع کنید. اما بعداً از کتابخانه جاوا حذف شد. می توانید آن را در اسناد Oracle جستجو کنید و ببینید که به عنوان منسوخ علامت گذاری شده است . چرا؟ زیرا به سادگی جریان را بدون هیچ کار اضافی متوقف کرد. به عنوان مثال، یک رشته می تواند با داده ها کار کند و چیزی را در آن تغییر دهد. سپس او در وسط کار ناگهان ناک اوت شد stop()- و تمام. هیچ خاموشی درست، هیچ آزادسازی منابع، حتی مدیریت خطا وجود نداشت - هیچ کدام از اینها اتفاق نیفتاد. این روش stop()، اغراق آمیز، به سادگی همه چیز را در مسیر خود نابود کرد. عملکرد آن را می توان با نحوه بیرون کشیدن دوشاخه از سوکت برای خاموش کردن رایانه مقایسه کرد. بله، می توانید به نتیجه دلخواه برسید. اما همه می دانند که در چند هفته دیگر رایانه به این دلیل "متشکرم" نخواهد گفت. به همین دلیل منطق قطع کردن نخ ها در جاوا تغییر کرد و اکنون از روش خاصی استفاده می شود - interrupt().

روش () Thread.interrupt

اگر متدی را روی یک رشته فراخوانی کنید چه اتفاقی می‌افتد interrupt()؟ 2 گزینه وجود دارد:
  1. اگر جسم در آن لحظه در حالت انتظار بود، برای مثال، joinیا sleep، انتظار قطع می شود و برنامه پرتاب می شود InterruptedException.
  2. اگر thread در آن لحظه در حالت کار بود، پرچم بولین شی تنظیم می شود interrupted.
اما ما باید شیء را از نظر ارزش این پرچم بررسی کنیم و کار را به درستی تکمیل کنیم! برای این منظور کلاس Threadمتد خاصی دارد - boolean isInterrupted(). بیایید به مثال ساعت از سخنرانی دوره اصلی برگردیم. برای راحتی، کمی ساده شده است:
public class Clock extends Thread {

   public static void main(String[] args) throws InterruptedException {
       Clock clock = new Clock();
       clock.start();

       Thread.sleep(10000);
       clock.interrupt();
   }

   public void run() {
       Thread current = Thread.currentThread();

       while (!current.isInterrupted())
       {
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               System.out.println("Работа потока была прервана");
               break;
           }
           System.out.println("Tik");
       }
   }
}
در مورد ما، ساعت هر ثانیه شروع می شود و شروع به تیک تاک کردن می کند. در 10 ثانیه جریان ساعت را قطع می کنیم. همانطور که می‌دانید، اگر رشته‌ای که ما می‌خواهیم قطع کنیم در یکی از حالت‌های انتظار باشد، نتیجه می‌شود InterruptedException. این نوع استثنا یک استثنا بررسی شده است، بنابراین به راحتی می توان آن را گرفت و منطق خاتمه برنامه ما را اجرا کرد. این کاری است که ما انجام دادیم. نتیجه ما این است: تیک تیک تیک تیک تیک تیک تیک تیک تیک کار تاپیک قطع شد Thread. برای تثبیت دانش خود، می توانید این سخنرانی ویدیویی در مورد چند رشته ای را تماشا کنید:
آن را به عنوان مواد اضافی عالی خدمت می کنند! در پایان، پس از مروری بر روش ها، دقیقاً می گوید که در ادامه دوره از چه چیزهایی عبور خواهیم کرد :) موفق باشید!
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION