۲۹ شهریور ۱۴۰۳

Techboy

اخبار و اطلاعات روز تکنولوژی

نحوه استفاده از callback در جاوا

نحوه استفاده از تماس‌های همگام و ناهمزمان در جاوا را بیاموزید - از جمله تماس‌های با عبارات لامبدا، CompletableFuture و موارد دیگر.

نحوه استفاده از تماس‌های همگام و ناهمزمان در جاوا را بیاموزید – از جمله تماس‌های با عبارات لامبدا، CompletableFuture و موارد دیگر.

عملیات برگشت به فراخوان در جاوا تابعی است که به تابع دیگری ارسال می‌شود و پس از انجام برخی اقدامات اجرا می‌شود. یک تماس برگشتی می تواند به صورت همزمان یا ناهمزمان اجرا شود. در مورد بازخوانی همزمان، یک تابع بلافاصله پس از دیگری اجرا می شود. در مورد بازخوانی ناهمزمان، یک تابع پس از مدت زمان نامشخصی اجرا می‌شود و در هیچ ترتیب خاصی با سایر توابع انجام نمی‌شود.

این مقاله شما را با callbacks در جاوا آشنا می‌کند، که با مثال کلاسیک callback به عنوان شنونده در الگوی طراحی قابل مشاهده شروع می‌شود. نمونه‌هایی از انواع پیاده‌سازی پاسخ به تماس همزمان و ناهمزمان، از جمله پاسخ به تماس عملکردی با استفاده از CompletableFuture را مشاهده خواهید کرد.

تماس‌های همگام در جاوا

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

همانطور که اشاره کردم، نمونه ای از یک تابع فراخوانی در الگوی طراحی قابل مشاهده یافت می شود. در یک رابط کاربری که نیاز به کلیک یک دکمه برای شروع برخی اقدامات دارد، می‌توانیم عملکرد برگشت به تماس را به عنوان یک شنونده روی کلیک آن دکمه منتقل کنیم. تابع شنونده منتظر می ماند تا دکمه کلیک شود، سپس پاسخ تماس شنونده را اجرا می کند.

اکنون اجازه دهید به چند نمونه از مفهوم بازگشت به تماس در کد نگاه کنیم.

بازخوانی ناشناس کلاس داخلی

هر زمان که یک رابط با پیاده سازی متد را به روش دیگری در جاوا ارسال می کنیم، از مفهوم تابع callback استفاده می کنیم. در کد زیر، رابط عملکردی Consumer و یک کلاس داخلی ناشناس (پیاده سازی بدون نام) را برای پیاده سازی متد accept() ارسال می کنیم.

Mechanoid Wasm را به سیستم های تعبیه شده و اینترنت اشیا می آورد

هنگامی که متد accept() پیاده سازی شد، اقدام را از روش performAction اجرا می کنیم. سپس روش accept() را از رابط Consumer اجرا می کنیم:


import java.util.function.Consumer;

public class AnonymousClassCallback {

  public static void main(String[] args) {
    performAction(new Consumer<String>() {
      @Override
      public void accept(String s) {
        System.out.println(s);
      }
    });
  }

  public static void performAction(Consumer<String> consumer) {
    System.out.println("Action is being performed...");
    consumer.accept("Callback is executed");
  }

}

خروجی این کد عبارت چاپی است:


Action is being performed... 

Callback is executed...

در این کد، رابط Consumer را به متد performAction() منتقل کردیم، سپس پس از عمل، متد accept() را فراخوانی کردیم. تمام شد.

ممکن است متوجه شوید که استفاده از یک کلاس داخلی ناشناس کاملاً پرمخاطب است. بهتر است به جای آن از لامبدا استفاده کنید. بیایید ببینیم وقتی از لامبدا برای عملکرد برگشت به تماس خود استفاده می کنیم چه اتفاقی می افتد.

بازخوانی لامبدا

در جاوا، ما می‌توانیم اینترفیس تابعی را با عبارت lambda پیاده‌سازی کنیم و آن را به یک متد ارسال کنیم، سپس پس از پایان عملیات، تابع را اجرا کنیم. در کد به این صورت است:


public class LambdaCallback {

  public static void main(String[] args) {
    performAction(() -> System.out.println("Callback function executed..."));
  }

  public static void performAction(Runnable runnable) {
    System.out.println("Action is being performed...");
    runnable.run();
  }

}

یک بار دیگر، خروجی بیان می‌کند که عمل در حال انجام است و تماس برگشتی اجرا می‌شود.

در این مثال، ممکن است متوجه شوید که ما رابط کاربری Runnable را در روش performAction ارسال کردیم. بنابراین، ما توانستیم پس از پایان عمل از روش performAction، متد run() را لغو و اجرا کنیم.

تماس‌های غیرهمزمان

اغلب، ما می خواهیم از یک متد پاسخ به تماس ناهمزمان استفاده کنیم، که به معنای روشی است که پس از انجام عمل، اما به صورت ناهمزمان با سایر فرآیندها فراخوانی می شود. زمانی که نیازی به فراخوانی روش برگشت پس از فرآیند دیگر نباشد، این ممکن است به عملکرد کمک کند.

بازخوانی موضوع ساده

اجازه دهید با ساده‌ترین روشی که می‌توانیم این عملیات تماس برگشتی غیرهمزمان را انجام دهیم، شروع می‌کنیم. در کد زیر ابتدا متد run() را از یک رابط کاربردی Runnable پیاده سازی می کنیم. سپس، یک Thread ایجاد می کنیم و از روش run() استفاده می کنیم که به تازگی در Thread پیاده سازی کرده ایم. در نهایت، Thread را برای اجرای ناهمزمان شروع می کنیم:


public class AsynchronousCallback {

  public static void main(String[] args) {
    Runnable runnable = () -> System.out.println("Callback executed...");
    AsynchronousCallback asynchronousCallback = new AsynchronousCallback();
    asynchronousCallback.performAsynchronousAction(runnable);
  }

  public void performAsynchronousAction(Runnable runnable) {
    new Thread(() -> {
      System.out.println("Processing Asynchronous Task...");
      runnable.run();
    }).start();
  }

}

خروجی در این مورد این است:


Processing Asynchronous Task...

Callback executed...

در کد بالا توجه کنید که ابتدا یک پیاده سازی برای متد run() از Runnable ایجاد کردیم. سپس، متد performAsynchronousAction() را فراخوانی کردیم و رابط عملکردی runnable را با پیاده‌سازی روش run() ارسال کردیم.

نحوه استفاده از کلمات کلیدی in، out و ref در NET Core

در داخل performAsynchronousAction() رابط runnable را پاس می کنیم و واسط Runnable دیگر را در Thread پیاده سازی می کنیم. با لامبدا سپس “Processing Asynchronous Task…” را چاپ می کنیم و در نهایت تابع callback run را که با پارامتر ارسال کردیم، فراخوانی می کنیم و “Callback executed…”

را چاپ می کنیم.

پاسخ به تماس موازی ناهمزمان

به غیر از فراخوانی تابع برگشت به تماس در عملیات ناهمزمان، می‌توانیم یک تابع پاسخ به تماس را به موازات یک تابع دیگر نیز فراخوانی کنیم. این بدان معناست که ما می‌توانیم دو رشته را شروع کنیم و آن متدها را به صورت موازی فراخوانی کنیم.

کد مشابه مثال قبلی خواهد بود، اما توجه داشته باشید که به جای فراخوانی مستقیم تابع callback، یک رشته جدید راه اندازی می کنیم و تابع callback را در این رشته جدید فراخوانی می کنیم:


// Omitted code from above…
public void performAsynchronousAction(Runnable runnable) {

    new Thread(() -> {
      System.out.println("Processing Asynchronous Task...");
      new Thread(runnable).start();
    }).start();
  }

خروجی این عملیات به شرح زیر است:


Processing Asynchronous Task...

Callback executed...

بازخوانی موازی ناهمزمان زمانی مفید است که ما نیازی به اجرای تابع callback بلافاصله پس از عمل از روش performAsynchronousAction() نداشته باشیم.

یک مثال در دنیای واقعی زمانی است که محصولی را به صورت آنلاین خریداری می‌کنیم و نیازی نیست منتظر بمانیم تا پرداخت تأیید شود، موجودی کالا بررسی شود و تمام آن فرآیندهای بارگیری سنگین. در آن صورت، می‌توانیم در حالی که فراخوانی برگشتی در پس‌زمینه اجرا می‌شود، کارهای دیگری انجام دهیم.

3 راه که devops می تواند از معماری پیوسته پشتیبانی کند

CompletableFuture callback

یک راه دیگر برای استفاده از تابع تماس ناهمزمان، استفاده از CompletableFuture API است. این API قدرتمند که در جاوا ۸ معرفی شده است، اجرای و ترکیب فراخوانی های متد ناهمزمان را تسهیل می کند. تمام کارهایی را که در مثال قبلی انجام دادیم انجام می دهد، مانند ایجاد یک Thread جدید و سپس شروع و مدیریت آن.

در مثال کد زیر، یک CompletableFuture جدید ایجاد می کنیم، سپس روش supplyAsync را با ارسال یک String فراخوانی می کنیم.

در مرحله بعد، یک CompletableFuture دیگر ایجاد خواهیم کرد که یک تابع پاسخ به تماس را thenApply می‌سازد تا با اولین تابعی که پیکربندی کردیم اجرا شود:


import java.util.concurrent.CompletableFuture;

public class CompletableFutureCallback {

  public static void main(String[] args) throws Exception {
    CompletableFuture<String> completableFuture
        = CompletableFuture.supplyAsync(() -> "Supply Async...");

    CompletableFuture<String> execution = completableFuture
        .thenApply(s -> s + " Callback executed...");

    System.out.println(execution.get());
  }

}

خروجی در اینجا این است:


Supply Async... Callback executed…

نتیجه گیری

توسعه‌های تماس در همه جا در توسعه نرم‌افزار وجود دارند، به طور گسترده در ابزارها، الگوهای طراحی و در برنامه‌ها استفاده می‌شوند. گاهی اوقات بدون اینکه متوجه شویم از آنها استفاده می کنیم.

برای کمک به نشان دادن کاربرد و تطبیق پذیری آنها در کد جاوا، انواع مختلفی از پیاده سازی های متداول را بررسی کرده ایم. در اینجا برخی از ویژگی های تماس های برگشتی وجود دارد که باید به خاطر بسپارید:

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