Scala.concurrent.Promise এর ব্যবহারের ক্ষেত্রে কী কী?


94

আমি এসআইপি -14 পড়ছি এবং এর ধারণাটি Futureনিখুঁত জ্ঞান এবং বোঝার জন্য সহজ করে তোলে। তবে এ সম্পর্কে দুটি প্রশ্ন রয়েছে Promise:

  1. এসআইপি বলে Depending on the implementation, it may be the case that p.future == p। এটা কিভাবে হতে পারে? হয় Futureএবং Promiseনা দুটি ভিন্ন ধরনের?

  2. আমাদের কখন ব্যবহার করা উচিত Promise? উদাহরণ producer and consumerকোড:

    import scala.concurrent.{ future, promise }
    val p = promise[T]
    val f = p.future
    
    val producer = future {
        val r = produceSomething()
        p success r
        continueDoingSomethingUnrelated()
    }
    val consumer = future {
        startDoingSomething()
        f onSuccess {
            case r => doSomethingWithResult()
        }
    }
    

পড়া সহজ তবে কি আমাদের কি এমন লেখার দরকার আছে? আমি এটি কেবল ভবিষ্যতের সাথে এবং এর মতো প্রতিশ্রুতি ছাড়াই বাস্তবায়নের চেষ্টা করেছি:

val f = future {
   produceSomething()
}

val producer = future {
   continueDoingSomethingUnrelated()
}

startDoingSomething()

val consumer = future {
  f onSuccess {
    case r => doSomethingWithResult()
  }
}

এই এবং প্রদত্ত উদাহরণের মধ্যে পার্থক্য কী এবং কোন প্রতিশ্রুতি আবশ্যক করে তোলে?


প্রথম উদাহরণে কন্টিনিউডসোমিংথিং আনলেলেটেড () একই থ্রেডে প্রোডমসোমথিং () পরে মূল্যায়ন করে।
সেনিয়া

4
# 1 প্রশ্নের উত্তরের জন্য, হ্যাঁ Futureএবং Promiseদুটি পৃথক প্রকারের, তবে আপনি github.com/scala/scala/blob/master/src/library/scala/concurrent/… থেকে দেখতে পারেন এই নির্দিষ্টকরণের Promiseপ্রয়োগটিও প্রসারিত Future
ডিলান

উত্তর:


118

প্রতিশ্রুতি এবং ভবিষ্যত পরিপূরক ধারণা। ভবিষ্যত একটি মান যা ভবিষ্যতে পুনরুদ্ধার করা হবে, ভাল, ভবিষ্যতে কোনও সময় এবং যখন ঘটনাটি ঘটে তখন আপনি এটিতে স্টাফ করতে পারেন। এটি কোনও গণনার পঠিত বা আউট আউটপয়েন্ট - এটি এমন একটি বিষয় যা থেকে আপনি একটি মান পুনরুদ্ধার করেন।

একটি প্রতিশ্রুতি, উপমা অনুসারে, গণনার লেখার দিক। আপনি একটি প্রতিশ্রুতি তৈরি করেন যা সেই জায়গা যেখানে আপনি গণনার ফলাফল রাখবেন এবং সেই প্রতিশ্রুতি থেকে আপনি এমন একটি ভবিষ্যত পাবেন যা প্রতিশ্রুতিতে প্রকাশিত ফলাফলটি পড়তে ব্যবহৃত হবে। আপনি যখন কোনও প্রতিশ্রুতিটি সম্পূর্ণ করেন, ব্যর্থতা বা সাফল্য দ্বারা, আপনি সম্পর্কিত ভবিষ্যতের সাথে সংযুক্ত সমস্ত আচরণকে ট্রিগার করবেন।

আপনার প্রথম প্রশ্ন সংক্রান্ত যে, তা কিভাবে হতে পারে যে একটি প্রতিশ্রুতি পি আমরা আছে জন্য p.future == p। আপনি এটি একক-আইটেম বাফারের মতো কল্পনা করতে পারেন - একটি ধারক যা প্রাথমিকভাবে শূন্য এবং আপনি আফটারওয়ার্ডস এমন একটি মান সংরক্ষণ করতে পারেন যা এটির সামগ্রীতে চিরতরে হয়ে যাবে। এখন, আপনার দৃষ্টিভঙ্গির উপর নির্ভর করে এটি একটি প্রতিশ্রুতি এবং ভবিষ্যত উভয়ই। এটি বাফারে মান লিখতে চান এমন ব্যক্তির পক্ষে প্রতিশ্রুতি। যে কেউ এই মানটি বাফারে রাখার জন্য অপেক্ষা করে তার পক্ষে ভবিষ্যত।

বিশেষত, স্কালার সমবর্তী API এর জন্য, আপনি যদি এখানে প্রতিশ্রুতিবদ্ধ বৈশিষ্ট্যটি একবার দেখে থাকেন তবে আপনি দেখতে পাবেন যে প্রতিশ্রুতি সহকারীর অবজেক্টের পদ্ধতিগুলি কীভাবে প্রয়োগ করা হয়েছে:

object Promise {

  /** Creates a promise object which can be completed with a value.
   *  
   *  @tparam T       the type of the value in the promise
   *  @return         the newly created `Promise` object
   */
  def apply[T](): Promise[T] = new impl.Promise.DefaultPromise[T]()

  /** Creates an already completed Promise with the specified exception.
   *  
   *  @tparam T       the type of the value in the promise
   *  @return         the newly created `Promise` object
   */
  def failed[T](exception: Throwable): Promise[T] = new impl.Promise.KeptPromise[T](Failure(exception))

  /** Creates an already completed Promise with the specified result.
   *  
   *  @tparam T       the type of the value in the promise
   *  @return         the newly created `Promise` object
   */
  def successful[T](result: T): Promise[T] = new impl.Promise.KeptPromise[T](Success(result))

}

এখন, প্রতিশ্রুতিগুলির বাস্তবায়ন, ডিফল্টপ্রাইমস এবং কেপট্রোমাইসগুলি এখানে পাওয়া যাবে । তারা উভয়ই একই নামের সাথে ঘটে এমন একটি বেস সামান্য বৈশিষ্ট্য প্রসারিত করে তবে এটি একটি পৃথক প্যাকেজে অবস্থিত:

private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] {
  def future: this.type = this
}

সুতরাং আপনি দেখতে পাচ্ছেন যে তারা কী বোঝায় p.future == p

DefaultPromiseআমি উপরে বর্ণিত বাফারটি হ'ব, যদিও KeptPromiseএটির তৈরি থেকে প্রাপ্ত মান সহ একটি বাফার।

আপনার উদাহরণ সম্পর্কে, ভবিষ্যতে আপনি যে ব্লকটি ব্যবহার করেন তা বাস্তবে পর্দার পিছনে একটি প্রতিশ্রুতি তৈরি করে। সংজ্ঞা যাক চেহারা futureমধ্যে এখানে :

def future[T](body: =>T)(implicit execctx: ExecutionContext): Future[T] = Future[T](body)

পদ্ধতিগুলির শৃঙ্খলা অনুসরণ করে আপনি প্ররোচিত হয়ে যান uture ভবিষ্যত :

private[concurrent] object Future {
  class PromiseCompletingRunnable[T](body: => T) extends Runnable {
    val promise = new Promise.DefaultPromise[T]()

    override def run() = {
      promise complete {
        try Success(body) catch { case NonFatal(e) => Failure(e) }
      }
    }
  }

  def apply[T](body: =>T)(implicit executor: ExecutionContext): scala.concurrent.Future[T] = {
    val runnable = new PromiseCompletingRunnable(body)
    executor.execute(runnable)
    runnable.promise.future
  }
}

সুতরাং, আপনি দেখতে পাচ্ছেন যে, আপনার প্রযোজক ব্লক থেকে আপনি যে ফলাফল পেয়েছেন তা প্রতিশ্রুতি হিসাবে ডেকে আনে।

লেটার সম্পাদনা :

বাস্তব-বিশ্বের ব্যবহার সম্পর্কে: বেশিরভাগ সময় আপনি সরাসরি প্রতিশ্রুতিগুলির সাথে চুক্তি করবেন না। আপনি যদি একটি লাইব্রেরি ব্যবহার করেন যা অ্যাসিঙ্ক্রোনাস গণনা সম্পাদন করে তবে আপনি কেবল লাইব্রেরির পদ্ধতি দ্বারা ফিরিয়ে দেওয়া ফিউচারগুলির সাথে কাজ করবেন। প্রতিশ্রুতিবদ্ধ হয়, এই ক্ষেত্রে, গ্রন্থাগার দ্বারা নির্মিত - আপনি কেবল এই পদ্ধতিগুলি কি পড়ার শেষের সাথে কাজ করছেন।

তবে আপনার যদি নিজের অ্যাসিঙ্ক্রোনাস এপিআই প্রয়োগ করতে হয় তবে আপনাকে তাদের সাথে কাজ শুরু করতে হবে। ধরুন আপনার উপরে একটি অ্যাসিঙ্ক এইচটিটিপি ক্লায়েন্ট প্রয়োগ করা দরকার, বলুন, নেটটি ty তারপরে আপনার কোডটি কিছুটা এ জাতীয় দেখাচ্ছে

    def makeHTTPCall(request: Request): Future[Response] = {
        val p = Promise[Response]
        registerOnCompleteCallback(buffer => {
            val response = makeResponse(buffer)
            p success response
        })
        p.future
    }

4
@ xiefei এর ব্যবহারের ক্ষেত্রে Promiseপ্রয়োগের কোড হওয়া উচিত। Futureএকটি দুর্দান্ত, কেবল পঠনযোগ্য জিনিস যা আপনি ক্লায়েন্ট কোডে প্রকাশ করতে পারেন। এছাড়াও, Future.future{...}সিনট্যাক্সটি কখনও কখনও জটিল হতে পারে।
ডিলান

11
আপনি এটি দেখতে পারেন: প্রতিশ্রুতি ছাড়া আপনার ভবিষ্যত থাকতে পারে না। যদি ভবিষ্যতে কোনও প্রতিশ্রুতি না হয় যা প্রথম স্থানে পূর্ণ হয় তবে কোনও মান ফিরিয়ে দিতে পারে না। প্রতিশ্রুতিগুলি alচ্ছিক নয়, এগুলি ভবিষ্যতের বাধ্যতামূলক লেখার দিক। আপনি কেবল ফিউচারের সাথে কাজ করতে পারবেন না কারণ তাদের ফেরতের মান দেওয়ার জন্য কেউ নেই।
মারিউস ড্যানিলা

4
আমি মনে করি আপনি বাস্তব বিশ্বের ব্যবহারগুলি দ্বারা কী বোঝাতে চেয়েছেন তা আমি দেখতে পেয়েছি: আপনাকে একটি উদাহরণ দেওয়ার জন্য আমি আমার প্রতিক্রিয়া আপডেট করেছি।
মারিউস ড্যানিলা

4
@ মারিয়াস: প্রদত্ত আসল বিশ্বের উদাহরণ বিবেচনা করে যদি মেক এইচটিটিপিসাল এভাবে প্রয়োগ করা হয়: def makeHTTPCall(request: Request): Future[Response] = { Future { registerOnCompleteCallback(buffer => { val response = makeResponse(buffer) response }) } }
পুণেটেক

4
@ পুনেটেক এর পরে আপনার ভবিষ্যত হবে যা registerOnCompleteCallback()শেষ হওয়ার পরেই সম্পূর্ণ হবে। এছাড়াও, এটি ফিরে আসে না Future[Response]। এটি Future[registerOnCompleteCallback() return type]পরিবর্তে ফিরে আসে ।
ইভজেনি ভেরেটেনিকভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.