java - আমরা কেন ল্যাবডা ফাংশনের ভিতরে থ্রেডকে#ঘুম() বলতে পারি না?




multithreading lambda (6)

আপনার সন্দেহ একটি ল্যাম্বডা এক্সপ্রেশন এবং একটি বেনাম শ্রেণীর স্কোপগুলি কীভাবে সংজ্ঞায়িত করা হয় সে সম্পর্কে একটি ভুল বোঝাবুঝির ভিত্তিতে উত্সাহিত হয়। নীচে, আমি এটি পরিষ্কার করার চেষ্টা করব।

লাম্বদা এক্সপ্রেশনগুলি স্কোপিংয়ের কোনও নতুন স্তরের পরিচয় দেয় না। এর অর্থ হ'ল এর অভ্যন্তরে আপনি কেবল একই জিনিসগুলিতে অ্যাক্সেস করতে পারবেন যা আপনি অবিলম্বে বন্ধ করা কোড ব্লকে অ্যাক্সেস করতে সক্ষম হবেন। documentation বলে দেখুন:

ল্যাম্বডা এক্সপ্রেশনগুলি নমনীয়ভাবে বাদ দেওয়া হয়েছে। এর অর্থ হ'ল তারা সুপারপাইপ থেকে কোনও নাম উত্তরাধিকারসূত্রে আসে না বা স্কোপিংয়ের একটি নতুন স্তরের পরিচয় দেয় না। ল্যাম্বডা এক্সপ্রেশনে ঘোষণাগুলি যেমন ঘের পরিবেশে থাকে তেমন ব্যাখ্যা করা হয়।

নামবিহীন ক্লাসগুলি আলাদাভাবে কাজ করে। তারা স্কোপিংয়ের একটি নতুন স্তর প্রবর্তন করে। তারা অনেকটা স্থানীয় শ্রেণির মতো আচরণ করে (এমন একটি শ্রেণি যা আপনি কোডের একটি ব্লকের ভিতরে ঘোষণা করেন), যদিও তাদের নির্মাণকারী থাকতে পারে না। docs বলে দেখুন:

স্থানীয় ক্লাসগুলির মতো, বেনাম শ্রেণীরা ভেরিয়েবল ক্যাপচার করতে পারে; ঘেরের সুযোগের স্থানীয় ভেরিয়েবলগুলিতে তাদের একই অ্যাক্সেস রয়েছে:

  • একটি বেনাম শ্রেণীর তার বদ্ধ শ্রেণীর সদস্যদের অ্যাক্সেস রয়েছে।
  • একটি বেনাম শ্রেণি চূড়ান্ত বা কার্যকরভাবে চূড়ান্ত হিসাবে ঘোষিত নয় এমন তার ঘেরের স্কোপগুলিতে স্থানীয় পরিবর্তনগুলি অ্যাক্সেস করতে পারে না।
  • নেস্টেড ক্লাসের মতো, বেনামে শ্রেণিতে কোনও প্রকারের (যেমন একটি ভেরিয়েবল) ঘোষণার সাথে একই নামযুক্ত সংযুক্তি স্কোপে থাকা অন্য কোনও ঘোষণাকে ছায়া দেয়। আরও তথ্যের জন্য ছায়া দেখুন।

এই প্রসঙ্গে, Thread অভ্যন্তরে স্থানীয় শ্রেণীর মতো কাজ করবে এবং এইভাবে এটি সরাসরি sleep() অ্যাক্সেস করতে সক্ষম হবে, যেহেতু এই পদ্ধতিটি তার আওতায় থাকবে। তবে ল্যাম্বডা অভিব্যক্তিতে sleep() Thread.sleep() পরিবেশে আপনি sleep() পারবেন না), যাতে আপনাকে অবশ্যই Thread.sleep() ব্যবহার করতে হবে। নোট করুন যে এই পদ্ধতিটি স্থিতিশীল এবং সুতরাং, কল করার জন্য এটির শ্রেণীর কোনও উদাহরণের প্রয়োজন নেই।

নীচের কোডটি আমাকে একটি সংকলন সময় ত্রুটি দিচ্ছে:

Thread t2 = new Thread(() -> {
    try { 
        sleep(1000);
    } 
    catch (InterruptedException e) {}
});

পদ্ধতি ঘুম (ইন্ট) টাইপ এ (যেখানে এ আমার শ্রেণীর নাম) টাইপটির জন্য অপরিজ্ঞাত

আমি যখন বেনামে অভ্যন্তরীণ শ্রেণি ব্যবহার করি তখন কোনও সংকলনের সময় ত্রুটি থাকে না:

Thread t1 = new Thread(){
    public void run(){
        try {
            sleep(1000);
        } catch (InterruptedException e) {}
    }
};

নীচের কোডটিও সূক্ষ্মভাবে কাজ করে:

Thread t3 = new Thread(() -> System.out.println("In lambda"));

ল্যাম্বডা এক্সপ্রেশন বডিটির ভিতরে কীভাবে জিনিসগুলি কাজ করে? সাহায্য করুন.

অনেক উত্তর থেকে, আমি দেখতে পাচ্ছি যে Thread.sleep(1000) ব্যবহার করে আমার প্রথম পদ্ধতির মাধ্যমে Thread.sleep(1000) সমাধান করা যেতে পারে। তবে, আমি সত্যিই প্রশংসা করব যদি কেউ আমাকে ব্যাখ্যা করতে পারে যে ল্যাম্বডা এক্সপ্রেশনটিতে কীভাবে সুযোগ এবং প্রসঙ্গটি কাজ করে।


আমি যে উত্তরটি সরবরাহ এবং স্বীকৃত হয়েছিল তা পছন্দ করি তবে খুব সহজ কথায় আপনি ভাবতে পারেন যে এটি বেনামে অভ্যন্তর শ্রেণি থেকে ল্যাম্বডায় পরিবর্তিত হয়েছে।

কোনও এআইসির ক্ষেত্রে, this আপনার প্রসারিত শ্রেণীর একটি উদাহরণকে বোঝায় (আপনার উদাহরণে Thread হচ্ছে), lambda expression ক্ষেত্রে, এটি ল্যাম্বডা এক্সপ্রেশনকে ঘিরে এমন শ্রেণীর একটি উদাহরণকে বোঝায় (যে শ্রেণি যাই হোক না কেন আপনার উদাহরণে)। এবং আমি আপনার ক্লাসে বাজি ধরছি যেখানে আপনি ল্যাম্বডা এক্সপ্রেশন ব্যবহার করেন সেখানে এমন sleep সংজ্ঞা দেওয়া হয়নি।


থ্রেড.স্লিপ স্থির পদ্ধতি ...

 Thread t2 = new Thread(() -> {
        try {
            Thread.sleep(1000);
        }
        catch (InterruptedException e) {}
    });

নিম্নলিখিত কোড কাজ করে:

    Thread t2 = new Thread(() -> {
        try { 
            Thread.sleep(1000);
        } 
        catch (InterruptedException e) {}
    });

কারণ Thread ক্লাসের Runnable আপনি যখন Runnable উদাহরণ তৈরি করছেন এবং পাস করছেন তখন Runnable sleep(int milliseconds) Thread ক্লাস থেকে একটি পদ্ধতি।

দ্বিতীয় পদ্ধতিতে, আপনি Thread বর্গের একটি বেনামে অভ্যন্তরীণ শ্রেণীর উদাহরণ তৈরি করছেন এবং এভাবে সমস্ত Thread শ্রেণীর পদ্ধতিতে অ্যাক্সেস রয়েছে।


Thread.sleep Thread ক্লাসে স্থির পদ্ধতি।

বেনাম শ্রেণিতে কোনও যোগ্যতা ছাড়াই আপনি সরাসরি sleep ডাকার কারণ হ'ল আপনি আসলে Thread থেকে উত্তরাধিকার সূত্রে প্রাপ্ত ক্লাসের প্রসঙ্গে। সুতরাং, sleep সেখানে অ্যাক্সেসযোগ্য।

তবে ল্যাম্বদা ক্ষেত্রে, আপনি Thread থেকে উত্তরাধিকার সূত্রে প্রাপ্ত কোনও শ্রেণিতে নেই। যে কোডটি চারপাশে ক্লাসে রয়েছে আপনি তার ভিতরে রয়েছেন। অতএব, sleep সরাসরি ডাকা যাবে না এবং আপনার Thread.sleep বলতে Thread.sleepdocumentation এটিকে সমর্থন করে:

ল্যাম্বডা এক্সপ্রেশনগুলি নমনীয়ভাবে বাদ দেওয়া হয়েছে। এর অর্থ হ'ল তারা সুপারপাইপ থেকে কোনও নাম উত্তরাধিকারসূত্রে আসে না বা স্কোপিংয়ের একটি নতুন স্তরের পরিচয় দেয় না। ল্যাম্বডা এক্সপ্রেশনে ঘোষণাগুলি যেমন ঘের পরিবেশে থাকে তেমন ব্যাখ্যা করা হয়।

মূলত এটি বলছে যে ল্যাম্বডারের অভ্যন্তরে, আপনি আসলে একইভাবে রয়েছেন যেন আপনি ল্যাম্বডারের বাইরে ছিলেন। আপনি যদি ল্যাম্বদার বাইরে sleep অ্যাক্সেস করতে না পারেন তবে আপনি ভিতরেও can't

এছাড়াও, এখানে লক্ষ্য করুন যে থ্রেড তৈরির দুটি উপায় যা আপনি এখানে দেখিয়েছেন তা স্বতন্ত্রভাবে আলাদা। ল্যাম্বডা একটিতে আপনি Thread Runnable কাছে Runnable পাস করছেন, অন্যদিকে বেনামে ক্লাস একের মধ্যে আপনি সরাসরি একটি Runnable শ্রেণি তৈরি করে একটি Thread তৈরি করছেন।


public void foo() {
    new Thread(() -> { sleep(1000); });
}

সমতুল্য

public void foo() {
    new Thread(this::lambda$0);
}
private void lambda$0() {
    sleep(1000);
}

সুতরাং সংকলক Thread sleep সন্ধান করবে না