Google
خانه / آموزش / نحوه ارتباط بین thread ها

نحوه ارتباط بین thread ها

thread یا رشته عبارتند از  واحد های کلی پردازش وظایف که هر برنامه می تواند تعدادی ترد داشته باشد. هر ترد اولویتی در سیستم دارد و تردهای ایجاد شده توسط یک ترد دیگر، اولویت هم سطح خواهند داشت. در اندروید هر برنامه یک ترد اصلی یا Main thread دارد و وقتی  thread جدیدی ایجاد می کنیم پردازش ها جدا از اتفاقات ترد اصلی روی می دهد. اما برای هماهنگ کردن و یا به عنوان مثال بازگشت جواب باید اینکار را بصورت دستی توسط message یا callback مدیریت کنیم.

در این مقاله می خواهیم نحوه ارتباط با این دو روش را برسی کنیم.

message

اصلی ترین راه ارتباط بین تردها پاس دادن پیام است. تردی که قرار است پیغام را دریافت کند باید دسترسی به صف پیغام ها داشته باشد که  messageQueue است و خود ترد ساده فاقد این کلاس است.

به شکل thread ساده و بدون messageQueue توجه کنید:

برای افزودن messageQueue از کلاس Looper استفاده می کنیم که messageQueue را برایمان فراهم می کند.

و بدین ترتیب messageQueue برایمان محیا می شود.

حال تردی که می خواهد مسیج ارسال کند نیاز به یک Handler دارد. وظیفه Handler ارسال و پردازش پیغام مربوط به messageQueue ترد ساخته شده اش می باشد. ( همچنین اجرای Runnable که موضوع این آموزش نیست). وقتی یک Handler جدید می سازیم به threadhd ای که درون آن ساخته شده و messageQueue مربوطه متصل می شود و message ها و runnable ها را به messageQueue مربوطه می رساند و یا از روی آن اجرا می کند. در اینجا برای ارسال پیام کافیست که یک هندلر بصورتی تعریف کنیم هردو ترد دسترسی داشته باشند ( بصورت public یا پاس دادن بصورت properties) در یکی توسط آن Messagehvshg ارسال کنیم و در دیگری Message را گرفته و پردازش کنیم.

به مثال ذیل توجه کنید:

ترد اول بعد از تمام شدن کارش زمان انجام کار را به ترد دوم پاس می دهد. در اینجا handler بصورت public تعریف شده بود.

Callback

در این روش ارتباط از طریق پاس دادن یک اینترفیس انجام می شود. برای اینکه مثال فرق کند ترد دریافت کننده پیام را در Ui thread قرار دادم. ( یعنی ترد جدیدی نساختم و در یک جایی در اکتیویتی تعریف کردم که می دانیم خود اکتیوتی در main thread یا همان Ui thread است).

برای درک بهتر کدها را اجرا کنید و نتایج را برسی کنید. در صورتی که سوال یا نکته ای داشتید کامنت کنید.

منبع: بایت کد

۸ دیدگاه

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

    private void test() {
    final ThreadCallBack callBack = new ThreadCallBack() {
    @Override
    public void onMessage(String s) {
    mTextView.setText(s);
    }
    };

    new Thread(new Runnable() {
    @Override
    public void run() {
    try {
    Thread.sleep(5000L);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    callBack.onMessage(“This is a Test”);
    }
    }).start();
    }

    interface ThreadCallBack {
    void onMessage(String message);
    }

    من تست کردم. این خطا رو داد:
    CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

    این نشون میده که onMessage روی ترد ui اجرا نشده. درسته؟

    • پرواضح است که نمی توانید UI را آپدیت کنید. وقتی سیگنیچر اینترفیسی را که در جای دیگر پیاده سازی شده صدا می زنید، در حقیقت آن پیاده سازی را در ترد صدا زننده اجرا می کنیم. پس وقتی در ترد دیگری غیر از اصلی متد پیاده سازی شده در ترد اصلی را صدا می زنیم به خاطر اطلاع نداشتن از Context به کامپوننت های UI دسترسی نداریم و نمی توان آن را آپدیت کرد. به نظرم یک نکته ای که اصلاً بهش توجه ندارید این است که هدف ارتباط بین دو ترد است، نه دسترسی به Context هم یا آپدیت UI از ترد دیگر. شما می توانستید در پیاده سازی اینترفیس یک متغیری را در ترد اصلی مقدار دهی کنید یا یک متدی که به کانتکس و UI ارتباط ندارد را صدا بزنید و به هدف ارتباط بین دوترد برسید. البته تشکر می کنم که این بحث و شروع کردید و خوشحال می شم که ادامه بدیم.

  2. ممنون. از توضیحتون.
    فقط یه نکته وجود داره.
    دریافت کننده پیام یعنی آبجکتی که از ThreadCallBack ساختید واسمش رو گذاشتید callBack ، ترد جدا گانه نیست و روی همون ترد ارسال کننده پیام اجرا میشه، یعنی روی ترد UI اجرا نمیشه.
    این یعنی اگه بخواید متد onMessage روی ترد UI اجرا بشه باید با استفاده از یه Handler با لوپر Main این کار رو انجام بدید.

    • ممنون از پیام شما. اگر درست متوجه شده باشم نکته شما در مورد بخش دوم کال بک بود. همانطور که در کد ملاحظه می کنید callBack در ترد UI ساخته شده و فقط سیگنیچرش به ترد دیگر پاس داده شده و اجرای نهایی در ترد اصلی (که implement شده) خواهد بود و نیازی به هندلر نخواهیم داشت. (هدفمون در بخش دوم استفاده نکردن از messaging و استفاده از callBack بود). در صورت امکان کد را یکبار اجرا و نتیجه را ببینید ولی اگر بازهم مشکل وجود داره خوشحال می شم بحث و ادامه بدیم.

      • خیر. callBack در ترد ui اصلی ساخته نشده در کلاس testThreadCallback ساخته شده که این کلاس در ترد ui نیست ظاهرا.
        وقتی در متد run متد onMessage رو صدا می زنید، این متد روی تردی که فراخوانی رو انجام داده اجرا میشه. در نتیجه دستوران متد onMessage روی ترد ui اجرا نمیشه.

  3. واااااای …واقعا دمت گرم عالی توضیح دادی خیلی وقت بود نمیتونستم این messageQueueو ارتباطش با handlerوthreadرو درک کنم…واقعا دمت گررررررم

دیدگاهتان را ثبت کنید

آدرس ایمیل شما منتشر نخواهد شدعلامتدارها لازمند *

*

bigtheme