জাভা থ্রেডলোকাল ভেরিয়েবলগুলি স্থির হওয়া উচিত


101

আমি এখানে থ্রেডলোকালের জন্য জাভাডোক পড়ছিলাম

https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ThreadLocal.html

এবং এটিতে "থ্রেডলোকাল উদাহরণগুলি এমন ক্লাসগুলিতে সাধারণত ব্যক্তিগত স্ট্যাটিক ক্ষেত্র যা একটি থ্রেডের সাথে রাষ্ট্রকে যুক্ত করতে চায় (যেমন, কোনও ব্যবহারকারী আইডি বা লেনদেন আইডি)"।

তবে আমার প্রশ্ন হ'ল কেন তারা এটিকে স্থির (সাধারণত) বানাতে বেছে নিয়েছিল - এটি "প্রতি থ্রেড" রাষ্ট্রের জন্য বিষয়গুলিকে কিছুটা বিভ্রান্ত করে তোলে তবে ক্ষেত্রগুলি স্থির থাকে?

উত্তর:


131

কারণ এটি যদি উদাহরণস্বরূপ ক্ষেত্রের ক্ষেত্র হয়, তবে এটি আসলে "প্রতি থ্রেড - প্রতি তদন্ত" প্রতি গ্যারান্টিযুক্ত নয়। এটি সাধারণত আপনি যে সার্থক সন্ধান করছেন তা নয়।

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


2
আমি এই ব্যাখ্যাটি পছন্দ করি কারণ এটি দেখায় যে থ্রেডলোকাল কীভাবে ব্যবহার করা যায়
কেলিফজে

4
প্রতি-থ্রেড-প্রতি-দৃষ্টান্ত একটি দরকারী শব্দার্থক হতে পারে, তবে সেই প্যাটার্নটির বেশিরভাগ ব্যবহারগুলিতে এতগুলি অবজেক্ট জড়িত যে ThreadLocalকোনও হ্যাশ-সেটের রেফারেন্স ধরে রাখার জন্য এটি ব্যবহার করা ভাল যা প্রতি থ্রেড দৃষ্টান্তে অবজেক্টগুলিকে মানচিত্র করে।
সুপারক্যাট

@ ফাংশনাল এর ঠিক অর্থ হ'ল অ-স্থির প্রতিটি উদাহরণের ThreadLocalনিজস্ব থ্রেড-লোকাল ডেটা থাকবে যদিও সেই ThreadLocalদৃষ্টান্তগুলি একই থ্রেডে উপস্থিত রয়েছে। আমি এটা মাত্র দুই অন্তত জনপ্রিয় প্যাটার্ন হতে পারে অনুমান করা - এটি অগত্যা যে কাজ করতে ভুল নয়
GEG

17

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


12

এটা হতে হবে না। গুরুত্বপূর্ণ বিষয়টি হ'ল এটি একটি সিঙ্গলটন হওয়া উচিত।


3

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


1

থ্রেড প্রতি প্রতি থ্রেডলোকালের জন্য ব্যবহারের অর্থ হ'ল যদি আপনি কোনও অবজেক্টের সমস্ত পদ্ধতিতে কিছু দৃশ্যমান হতে চান এবং এটি কোনও সাধারণ ক্ষেত্রে যেমন চান তেমন অ্যাক্সেসকে সিঙ্ক্রোনাইজ না করে এটি থ্রেডটি নিরাপদ রাখতে চান।


1

পড়ুন এই , এই ভাল করে বুঝতে দিতে।

সংক্ষেপে, ThreadLocalঅবজেক্টটি কী-মানচিত্রের মানচিত্রের মতো কাজ করে। যখন থ্রেডটি ThreadLocal get/setপদ্ধতিটি আহ্বান করবে, তখন এটি মানচিত্রের কীতে থ্রেডের অবজেক্টটি এবং মানচিত্রের মানটির পুনরুদ্ধার / সঞ্চয় করবে। এ কারণেই বিভিন্ন থ্রেডের মানটির আলাদা আলাদা অনুলিপি করা হয়েছে (যে আপনি স্থানীয়ভাবে সঞ্চয় করতে চান), কারণ এটি বিভিন্ন মানচিত্রের প্রবেশে থাকে।

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


-1

static final ThreadLocal ভেরিয়েবলগুলি থ্রেড নিরাপদ।

staticথ্রেডলোকাল ভেরিয়েবলকে কেবলমাত্র সংশ্লিষ্ট থ্রেডের জন্য একাধিক ক্লাসে উপলব্ধ করে তোলে। এটি একাধিক ক্লাস জুড়ে সম্পর্কিত থ্রেড স্থানীয় ভেরিয়েবলগুলির একধরণের গ্লোবাল ভেরিয়েবল ডেকারেশন।

আমরা নিম্নলিখিত কোড নমুনা দিয়ে এই থ্রেড সুরক্ষা চেক করতে পারেন।

  • CurrentUser - থ্রেডলোকলে বর্তমান ব্যবহারকারীর আইডি সঞ্চয় করে
  • TestService- পদ্ধতি সহ সহজ পরিষেবা - getUser()কারেন্ট ইউজার থেকে বর্তমান ব্যবহারকারীর আনতে।
  • TestThread - এই শ্রেণিটি একাধিক থ্রেড তৈরি করতে ব্যবহার করে এবং একই সাথে ইউজারাইড সেট করে

public class CurrentUser

public class CurrentUser {
private static final ThreadLocal<String> CURRENT = new ThreadLocal<String>();

public static ThreadLocal<String> getCurrent() {
    return CURRENT;
}

public static void setCurrent(String user) {
    CURRENT.set(user);
}

}

public class TestService {

public String getUser() {
    return CurrentUser.getCurrent().get();
}

}

import java.util.ArrayList;
import java.util.List;

public class TestThread {

public static void main(String[] args) {

  List<Integer> integerList = new ArrayList<>();

  //creates a List of 100 integers
  for (int i = 0; i < 100; i++) {

    integerList.add(i);
  }

  //parallel stream to test concurrent thread execution
  integerList.parallelStream().forEach(intValue -> {

    //All concurrent thread will set the user as "intValue"
    CurrentUser.setCurrent("" + intValue);
    //Thread creates a sample instance for TestService class
    TestService testService = new TestService();
    //Print the respective thread name along with "intValue" value and current user. 
    System.out.println("Start-"+Thread.currentThread().getName()+"->"+intValue + "->" + testService.getUser());

    try {
      //all concurrent thread will wait for 3 seconds
      Thread.sleep(3000l);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    //Print the respective thread name along with "intValue" value and current user.
    System.out.println("End-"+Thread.currentThread().getName()+"->"+intValue + "->" + testService.getUser());
  });

}

}

টেস্টথ্রেড মূল ক্লাস চালান। আউটপুট -

Start-main->62->62
Start-ForkJoinPool.commonPool-worker-2->31->31
Start-ForkJoinPool.commonPool-worker-3->81->81
Start-ForkJoinPool.commonPool-worker-1->87->87
End-main->62->62
End-ForkJoinPool.commonPool-worker-1->87->87
End-ForkJoinPool.commonPool-worker-2->31->31
End-ForkJoinPool.commonPool-worker-3->81->81
Start-ForkJoinPool.commonPool-worker-2->32->32
Start-ForkJoinPool.commonPool-worker-3->82->82
Start-ForkJoinPool.commonPool-worker-1->88->88
Start-main->63->63
End-ForkJoinPool.commonPool-worker-1->88->88
End-main->63->63
...

বিশ্লেষণের সারাংশ

  1. "মূল" থ্রেড শুরু হয় এবং বর্তমান ব্যবহারকারীকে "62" হিসাবে সেট করে, সমান্তরালভাবে "ফোর্কজাইনপুল ডটকমপুল-কর্মী -২" থ্রেড শুরু হয় এবং বর্তমান ব্যবহারকারীকে "31" হিসাবে সেট করে, সমান্তরালভাবে "ফোরকজাইনপুল.কম.পুল-কর্মী -৩" থ্রেড শুরু হয়ে বর্তমান সেট করে "81" হিসাবে ব্যবহারকারী সমান্তরালভাবে "ফোর্কজাইনপুল.কম.পুল-কর্মী -১" থ্রেড শুরু করে এবং বর্তমান ব্যবহারকারীকে "87" হিসাবে স্টার্ট-মেইন-> 62-> 62 স্টার্ট-ফর্কজইনপুল.কম.পুল-কর্মী -2-> 31-> 31 হিসাবে সেট করুন স্টার্ট-ফর্কজইনপুল.কম.পুল-কর্মী -3-> 81-> 81 স্টার্ট-ফর্কজইনপুল.কম.পুল-কর্মী -1-> 87-> 87
  2. এই উপরের সমস্ত থ্রেড 3 সেকেন্ডের জন্য ঘুমাবে
  3. mainসম্পাদনা সমাপ্ত হয় এবং বর্তমান ব্যবহারকারীকে "62" হিসাবে মুদ্রণ করে, সমান্তরালভাবে ForkJoinPool.commonPool-worker-1নির্বাহ শেষ হয় এবং বর্তমান ব্যবহারকারীকে "87" হিসাবে মুদ্রণ করে, সমান্তরালভাবে ForkJoinPool.commonPool-worker-2নির্বাহ শেষ হয় এবং বর্তমান ব্যবহারকারীকে "31" হিসাবে মুদ্রণ করে, সমান্তরালভাবে ForkJoinPool.commonPool-worker-3কার্যকর হয় এবং বর্তমান ব্যবহারকারীটিকে "81" হিসাবে মুদ্রণ করে

অনুমান

সাম্প্রতিক থ্রেডগুলি "স্ট্যাটিক চূড়ান্ত থ্রেডলোকাল" হিসাবে ঘোষিত থাকলেও সঠিক ব্যবহারকারীর পুনরুদ্ধার করতে সক্ষম

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.