CodeGym /وبلاگ جاوا /Random-FA /Multithreading: کاری که متدهای کلاس Thread انجام می دهند
John Squirrels
مرحله
San Francisco

Multithreading: کاری که متدهای کلاس Thread انجام می دهند

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

متد Thread.start()

بیایید با تکرار خودمان شروع کنیم. همانطور که احتمالاً به خاطر دارید، می‌توانید با واداشتن کلاس خود به Threadکلاس و نادیده گرفتن run()متد، یک رشته ایجاد کنید. اما البته خود به خود شروع نخواهد شد. برای این کار، متد شیء خود را فراخوانی می کنیم start(). Multithreading: کاری که متدهای کلاس Thread انجام می دهند - 2بیایید مثال درس قبل را یادآوری کنیم:

public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("Thread executed: " + getName());
   }
}


public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
نکته: برای شروع یک تاپیک، بایدstart()متد special را فراخوانی کنید تاrun()متد! این یک خطا آسان است، به خصوص زمانی که برای اولین بار شروع به مطالعه چند رشته ای می کنید. run()در مثال ما، اگر به جای 10 بار متد رافراخوانی کنیدstart()، این را دریافت خواهید کرد:

public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
به نتایج برنامه ما نگاه کنید: Thread executed: Thread-0 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-7 Thread executed: Thread-8 Thread executed: Thread-9 به ترتیب خروجی نگاه کنید: همه چیز به ترتیب کامل اتفاق می افتد. عجیبه، ها؟ ما به این عادت نکرده‌ایم، زیرا می‌دانیم که ترتیب شروع و اجرای رشته‌ها توسط یک عقل برتر در سیستم عامل ما تعیین می‌شود: زمان‌بندی رشته. شاید ما فقط شانس آوردیم؟ البته این از شانس نیست. می توانید با اجرای برنامه چند بار دیگر این موضوع را تأیید کنید. مسئله این است که فراخوانی run()متد مستقیماً ربطی به multithreading ندارد. در این صورت، برنامه روی رشته اصلی، همان رشته ای که متد را اجرا می کند، اجرا می شود main(). به سادگی 10 خط را روی کنسول چاپ می کند و تمام. 10 موضوع شروع نشده است. بنابراین، این را در آینده به خاطر بسپارید و مدام خود را بررسی کنید. اگر می خواهید run()متد فراخوانی شود، تماس بگیرید start(). بیایید جلوتر برویم.

متد Thread.sleep().

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

public class Main {

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

       long start = System.currentTimeMillis();

       Thread.sleep(3000);

       System.out.println(" - How long did I sleep? \n - " + ((System.currentTimeMillis()-start)) / 1000 + " seconds");

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

متد () Thread.join

Multithreading: کاری که متدهای کلاس Thread انجام می دهند - 4این join()روش اجرای thread فعلی را تا زمانی که رشته دیگری تمام شود به حالت تعلیق در می آورد. اگر 2 رشته داشته باشیم، t1و t2، و می نویسیم

t1.join()
سپس t2تا زمانی که کار خود را تمام نکرده است شروع نمی شود t1. از این join()روش می توان برای تضمین ترتیب اجرای thread ها استفاده کرد. بیایید نحوه join()عملکرد روش را در مثال زیر در نظر بگیریم:

public class ThreadExample extends Thread {

   @Override
   public void run() {

       System.out.println("Thread started: " + getName());

       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("Thread " + getName() + " is finished.");
   }
}


public class Main {

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

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

       t1.start();


 /* The second thread (t2) will start running only after the first thread (t1)
       is finished (or an exception is thrown) */
       try {
           t1.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       t2.start();

       // The main thread will continue running only after t1 and t2 have finished
       try {
           t1.join();
           t2.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println("All threads have finished. The program is finished.");

   }
}
ما یک ThreadExampleکلاس ساده ایجاد کردیم. وظیفه آن این است که پیغامی مبنی بر شروع تاپیک نمایش داده شود، به مدت 5 ثانیه به خواب رفته و در نهایت اعلام کند که کار تمام شده است. یک تکه کیک. منطق اصلی در Mainکلاس است. به نظرات نگاه کنید: ما از join()روشی برای مدیریت موفقیت آمیز ترتیب اجرای رشته ها استفاده می کنیم. اگر به خاطر دارید که چگونه این موضوع را شروع کردیم، دستور اجرا توسط زمان‌بندی رشته مدیریت می‌شود. این رشته ها را به صلاحدید خود اجرا می کند: هر بار به روشی متفاوت. در اینجا از روشی استفاده می‌کنیم که تضمین می‌کنیم t1ابتدا نخ شروع و اجرا می‌شود، سپس t2thread و تنها پس از آن موضوع اصلی برنامه ادامه می‌یابد. در حال حرکت در برنامه‌های واقعی، اغلب موقعیت‌هایی را می‌بینید که لازم است اجرای یک رشته را قطع کنید. به عنوان مثال، موضوع ما در حال اجرا است، اما منتظر یک رویداد یا شرایط خاص است. اگر اتفاق بیفتد، نخ متوقف می شود. اگر نوعی 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("The thread was interrupted");
               break;
           }
           System.out.println("Tick");
       }
   }
}
در این حالت، ساعت شروع می شود و هر ثانیه شروع به تیک تاک می کند. در ثانیه 10، رشته ساعت را قطع می کنیم. همانطور که می‌دانید، اگر رشته‌ای که می‌خواهیم قطع کنیم در یکی از حالت‌های انتظار باشد، نتیجه یک InterruptedException. این یک استثنا بررسی شده است، بنابراین ما می توانیم به راحتی آن را بگیریم و منطق خود را برای اتمام برنامه اجرا کنیم. و این همان کاری است که ما انجام دادیم. نتیجه ما این است: تیک تیک تیک تیک تیک تیک تیک تیکThread موضوع قطع شد . موفق باشید!
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION