JavaRush /وبلاگ جاوا /Random-FA /مثال SynchronousQueue در جاوا - حل مشکل Producer Consumer...
profeg
مرحله

مثال SynchronousQueue در جاوا - حل مشکل Producer Consumer

در گروه منتشر شد
مثال SynchronousQueue در جاوا - حل مشکل Producer Consumer
SynchronousQueue نوع خاصی از BlockingQueue است که در آن هر عملیات درج باید منتظر دستور حذف مربوطه در رشته دیگر باشد و بالعکس. هنگامی که متد put() را در یک SynchronousQueue فراخوانی می کنید ، تا زمانی که رشته دیگری آن عنصر را از آن بگیرد، مسدود می شود. بر این اساس، اگر thread دیگری سعی کند عنصری را از آن حذف کند، و عنصر در آنجا نباشد، آن thread بلوک می‌کند تا زمانی که نخ دیگر عنصر را در صف قرار دهد. شما می توانید SynchronousQueue را به عنوان یک ورزشکار ( نخ ) در نظر بگیرید که با مشعل المپیک می دود، او با مشعل می دود (شیئی که روی آن ارسال می شود) و آن را به ورزشکار دیگری که در طرف دیگر منتظر است می دهد. اگر به نام آن دقت کنید، متوجه می شوید که SynchronousQueue به دلیلی به این نام نامگذاری شده است؛ داده ها را به صورت همزمان به رشته دیگری منتقل می کند . منتظر می ماند تا کسی داده ها را به جای قرار دادن و خروج از آن (عملیات ناهمزمان) دریافت کند. اگر با CSP و Ada آشنایی دارید، می‌دانید که صف‌های همگام‌سازی شده شبیه به جلسه موضوعات هستند. آنها به خوبی برای ساختارهای انتقال کنترلی مناسب هستند که در آنها یک شی در حال اجرا در یک رشته باید با یک شی در رشته دیگر همگام شود تا برخی از اطلاعات، رویدادها یا وظایف را به آن منتقل کند. در آموزش های قبلی برنامه نویسی چند رشته ای، یاد گرفتیم که چگونه مشکل تولیدکننده-مصرف کننده را با استفاده از روش های انتظار و اعلان و BlockingQueue حل کنیم . اکنون نحوه اعمال الگوی تولیدکننده-مصرف کننده را با استفاده از SynchronousQueue خواهیم آموخت . این کلاس علاوه بر این از رفتار منصفانه برای سفارش دادن به انتظارات نخ های تولید کننده و مصرف کننده پشتیبانی می کند. به طور پیش فرض، این سفارش تضمین نمی شود. با این حال، صف‌هایی که با ویژگی‌های منصفانه ایجاد می‌شوند ، دسترسی به رشته‌ها را در صف FIFO (Firs In First Out) تضمین می‌کنند.
تولید کننده/مصرف کننده با استفاده از SynchronousQueue در جاوا.
مثال SynchronousQueue در جاوا - حل مشکل Producer Consumer - 1 همانطور که در بالا گفتم، برای درک ارتباطات بین رشته ای در هر زبان برنامه نویسی، هیچ چیز بهتر از مشکل تولیدکننده-مصرف کننده نیست. در این مشکل، یک نخ به عنوان تولید کننده ای عمل می کند که رویدادها و وظایف را تولید می کند و نخ دیگر به عنوان مصرف کننده آن عمل می کند. یک بافر مشترک برای انتقال داده از تولید کننده به مصرف کننده استفاده می شود. مشکل حل این مشکل در موارد شدید اتفاق می افتد، به عنوان مثال، زمانی که سازنده مجبور می شود منتظر بماند زیرا ... بافر پر است یا مصرف کننده مجبور است منتظر بماند زیرا بافر خالی است این به راحتی حل شد، زیرا ... صف مسدود کردن نه تنها یک بافر برای ذخیره داده‌ها، بلکه کنترل جریان نیز فراهم می‌کند، رشته‌ای که متد put() را فراخوانی می‌کند (Producer) را در صورت پر بودن بافر مسدود می‌کند، و رشته‌ای را که متد take() را فرا می‌خواند مسدود می‌کند (Consumer) اگر بافر خالی بود اکنون همین مشکل را با استفاده از SynchronousQueue، نوع خاصی از مجموعه‌های موازی با ظرفیت صفر، حل خواهیم کرد. در مثال زیر دو رشته به نام‌های PRODUCER و Consumer داریم (همیشه برای نخ‌ها نام بگذارید، این یک سبک برنامه‌نویسی چند رشته‌ای بسیار خوب است) تاپیک اول امتیاز را در بازی ارسال می‌کند و تاپیک دوم آن را مصرف می‌کند. امتیاز در بازی چیزی بیش از یک شی از نوع String نیست. اما اگر برنامه را با نوع دیگری اجرا کنید، تفاوتی متوجه نمی شوید. برای اینکه بفهمید SynchronousQueue چگونه کار می کند و چگونه مشکل تولیدکننده-مصرف کننده را حل کنید، باید: یا برنامه را برای اشکال زدایی (اشکال زدایی) در محیط Eclipse اجرا کنید ، یا به سادگی رشته تولید کننده را با نظر دادن به consumer.start(); اگر نخ مصرف کننده در حال اجرا نباشد، رشته تولید کننده در queue.put(event) مسدود می شود. در صورت اجرا، نمی توانید مشاهده کنید که تهیه کننده [تولیدکننده] رویداد :FOUR را منتشر می کند. این اتفاق می افتد زیرا رفتار خاص SynchronousQueue، که تضمین می‌کند تا زمانی که رشته‌ای دیگر داده‌ها را بگیرد، داده‌های ارسال کننده رشته مسدود می‌شوند و بالعکس. شما می توانید بقیه کد را با کامنت تولید کننده.start(); و فقط موضوع مصرف کننده را شروع می کند. اگر به دقت بررسی کنید که برنامه چه خروجی هایی دارد، متوجه خواهید شد که ترتیب خروجی ها برعکس شده است. به نظر می‌رسد که رشته [مصرف‌کننده] داده‌ها را قبل از تولید رشته [تولیدکننده] گرفته است . این به این دلیل است که SynchronousQueue به طور پیش فرض صف بندی را تضمین نمی کند. اما قوانین انصافی دارد که دسترسی به رشته ها را به ترتیب FIFO تنظیم می کند. شما می توانید این قوانین را با ارسال درست به سازنده SynchronousQueue اضافه بار مانند زیر فعال کنید: import java.util.concurrent.SynchronousQueue; /** * Java Program to solve Producer Consumer problem using SynchronousQueue. A * call to put() will block until there is a corresponding thread to take() that * element. * * @author Javin Paul */ public class SynchronousQueueDemo{ public static void main(String args[]) { final SynchronousQueue queue = new SynchronousQueue (); Thread producer = new Thread("PRODUCER") { public void run() { String event = "FOUR"; try { queue.put(event); // thread will block here System.out.printf("[%s] published event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; producer.start(); // starting publisher thread Thread consumer = new Thread("CONSUMER") { public void run() { try { String event = queue.take(); // thread will block here System.out.printf("[%s] consumed event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; consumer.start(); // starting consumer thread } } Output: [CONSUMER] consumed event : FOUR [PRODUCER] published event : FOUR new SynchronousQueue(boolean fair).
آنچه باید در مورد SynchronousQueue در جاوا به خاطر بسپارید.

در اینجا برخی از ویژگی های مهم این نوع خاص از صف مسدود کردن در جاوا آورده شده است. انتقال داده ها از یک رشته به رشته دیگر به صورت هماهنگ بسیار مفید است. این صف ظرفیت ندارد و تا زمانی که موضوع دیگری آن را آزاد نکند مسدود می شود.

  1. SynchronousQueue بلوک می کند و تا زمانی که یک رشته برای گرفتن داده آماده شود، دیگری سعی می کند داده ها را قرار دهد.
  2. SynchronousQueue حجم ندارد. یعنی حاوی داده نیست.
  3. SynchronousQueue برای پیاده سازی یک استراتژی صف جلو استفاده می شود، جایی که یک رشته کنترل را به یک رشته منتظر منتقل می کند، یا در صورت اجازه، یک رشته جدید ایجاد می کند، در غیر این صورت کنترل منتقل نمی شود.
  4. این صف به داده های پوچ اجازه نمی دهد. تلاش برای افزودن یک عنصر تهی، یک NullPointerException ایجاد می کند .
  5. اگر از روش‌های دیگری از مجموعه (مانند حاوی) استفاده می‌کنید، SynchronousQueue مانند یک مجموعه خالی عمل می‌کند.
  6. شما نمی توانید از روش SynchronousQueue استفاده کنید زیرا عنصر فقط زمانی وجود دارد که بخواهید آن را حذف کنید. همچنین، تا زمانی که رشته دیگری سعی در حذف آن نداشته باشد، نمی‌توانید عناصر را وارد کنید (با استفاده از هر روشی).
  7. شما نمی توانید از تکرار کننده برای SynchronousQueue استفاده کنید زیرا... هیچ عنصری ندارد
  8. SynchronousQueue را می توان با قوانین منصفانه ایجاد کرد که در آن دسترسی به رشته ها به ترتیب FIFO تضمین شده است.
شاید همه چیز در مورد SynchronousQueue در جاوا باشد. ما به برخی از ویژگی های خاص این مجموعه چند رشته ای نگاه کردیم و یاد گرفتیم که چگونه مشکل کلاسیک تولید کننده-مصرف کننده را با استفاده از SynchronousQueue در جاوا حل کنیم. به هر حال، نامیدن آن به عنوان Queue کاملاً صحیح نیست، زیرا ... این شامل عناصر نیست. فراخوانی برای put() تکمیل نخواهد شد تا زمانی که رشته دیگری فراخوانی () را نگیرد. درست تر است که آن را به عنوان محل ملاقات رشته ها در نظر بگیریم، جایی که آنها یک شی را به اشتراک می گذارند. به عبارت دیگر، این یک ابزار برای ارسال هماهنگ اشیاء در جاوا است، شاید جایگزین ایمن‌تری برای روش انتظار و اطلاع‌رسانی باشد .
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION