4.3.1। উদাহরণ: ডেলিগেশন ব্যবহার করে যানবাহন ট্র্যাকার
প্রতিনিধি দলের আরও উল্লেখযোগ্য উদাহরণ হিসাবে, চলুন যানবাহন ট্র্যাকারের একটি সংস্করণ তৈরি করুন যা একটি থ্রেড-নিরাপদ শ্রেণিতে প্রতিনিধিত্ব করে। আমরা অবস্থানগুলিতে একটি মানচিত্রে সংরক্ষণ করি, সুতরাং আমরা একটি থ্রেড-নিরাপদ মানচিত্রের প্রয়োগ দিয়ে শুরু করি ConcurrentHashMap। আমরা MutablePointলিস্টিং ৪.6-তে প্রদর্শিত পরিবর্তে স্থাবর পয়েন্ট শ্রেণি ব্যবহার করে অবস্থানটি সঞ্চয় করি store
তালিকা 4.6। DelegatingVehicleTracker দ্বারা ব্যবহৃত অপরিবর্তনীয় পয়েন্ট শ্রেণি।
class Point{
public final int x, y;
public Point() {
this.x=0; this.y=0;
}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
Pointথ্রেড-নিরাপদ কারণ এটি পরিবর্তনযোগ্য। অপরিবর্তনীয় মানগুলি অবাধে ভাগ করে নেওয়া এবং প্রকাশ করা যেতে পারে, সুতরাং সেগুলি ফেরত দেওয়ার সময় আমাদের আর কপি করার দরকার নেই।
DelegatingVehicleTrackerতালিকাভুক্ত 4.7 কোনও সুস্পষ্ট সিঙ্ক্রোনাইজেশন ব্যবহার করে না; রাষ্ট্রের সমস্ত অ্যাক্সেস পরিচালনা করে ConcurrentHashMapএবং মানচিত্রের সমস্ত কী এবং মান অপরিবর্তনীয়।
তালিকা 4.7। একটি সাম্প্রতিক হ্যাশম্যাপে থ্রেড সুরক্ষা প্রদান করা।
public class DelegatingVehicleTracker {
private final ConcurrentMap<String, Point> locations;
private final Map<String, Point> unmodifiableMap;
public DelegatingVehicleTracker(Map<String, Point> points) {
this.locations = new ConcurrentHashMap<String, Point>(points);
this.unmodifiableMap = Collections.unmodifiableMap(locations);
}
public Map<String, Point> getLocations(){
return this.unmodifiableMap; // User cannot update point(x,y) as Point is immutable
}
public Point getLocation(String id) {
return locations.get(id);
}
public void setLocation(String id, int x, int y) {
if(locations.replace(id, new Point(x, y)) == null) {
throw new IllegalArgumentException("invalid vehicle name: " + id);
}
}
}
আমরা যদি MutablePointপয়েন্টের পরিবর্তে আসল ক্লাসটি ব্যবহার করে থাকি, তবে getLocationsথ্রেড-নিরাপদ নয় এমন পরিবর্তনীয় অবস্থার একটি রেফারেন্স প্রকাশ করে আমরা এনক্যাপসুলেশনটি ভেঙে ফেলি। লক্ষ্য করুন যে আমরা গাড়ির ট্র্যাকার শ্রেণির আচরণ কিছুটা পরিবর্তন করেছি; মনিটর সংস্করণটি অবস্থানগুলির একটি স্ন্যাপশট ফেরত দেওয়ার সময়, প্রতিনিধি সংস্করণটি গাড়ির অবস্থানগুলির একটি অবিশ্বাস্য তবে "লাইভ" দৃশ্য প্রদান করে। এর অর্থ হ'ল যদি থ্রেড এ কল getLocationsএবং থ্রেড বি পরে কিছু পয়েন্টের অবস্থান পরিবর্তন করে তবে সেই পরিবর্তনগুলি মানচিত্রে থ্রেড এ এ ফিরে আসে are
4.3.2। ইন্ডিপেন্ডেন্ট স্টেট ভেরিয়েবলস
আমরা অন্তর্নিহিত রাষ্ট্র ভেরিয়েবলগুলি যতক্ষণ না স্বতন্ত্র, ততক্ষণ একের অধিক অন্তর্নিহিত রাষ্ট্র পরিবর্তনশীলকে থ্রেড সুরক্ষাও অর্পণ করতে পারি, অর্থাত সম্মিলিত শ্রেণি একাধিক রাষ্ট্রের ভেরিয়েবলগুলিতে জড়িত কোনও আক্রমণকারীকে চাপায় না।
VisualComponentতালিকাভুক্তকরণে 4.9 একটি গ্রাফিকাল উপাদান যা ক্লায়েন্টদের মাউস এবং কীস্ট্রোক ইভেন্টের জন্য শ্রোতাদের নিবন্ধিত করতে দেয়। এটি প্রতিটি ধরণের নিবন্ধিত শ্রোতাদের একটি তালিকা বজায় রাখে, যাতে কোনও ইভেন্ট যখন ঘটে তখন উপযুক্ত শ্রোতাদের আহ্বান জানানো যায়। তবে মাউস শ্রোতাদের এবং কী শ্রোতার সেটগুলির মধ্যে কোনও সম্পর্ক নেই; দুটি স্বতন্ত্র, এবং সেইজন্য VisualComponentএটির থ্রেড সুরক্ষা বাধ্যবাধকতা দুটি অন্তর্নিহিত থ্রেড-নিরাপদ তালিকার কাছে অর্পণ করতে পারে।
তালিকা 4.9। একাধিক অন্তর্নিহিত স্টেট ভেরিয়েবলগুলিতে থ্রেড সুরক্ষা প্রদান করা।
public class VisualComponent {
private final List<KeyListener> keyListeners
= new CopyOnWriteArrayList<KeyListener>();
private final List<MouseListener> mouseListeners
= new CopyOnWriteArrayList<MouseListener>();
public void addKeyListener(KeyListener listener) {
keyListeners.add(listener);
}
public void addMouseListener(MouseListener listener) {
mouseListeners.add(listener);
}
public void removeKeyListener(KeyListener listener) {
keyListeners.remove(listener);
}
public void removeMouseListener(MouseListener listener) {
mouseListeners.remove(listener);
}
}
VisualComponentCopyOnWriteArrayListপ্রতিটি শ্রোতার তালিকা সংরক্ষণ করতে একটি ব্যবহার করে ; এটি একটি থ্রেড-নিরাপদ তালিকা বাস্তবায়ন শ্রোতার তালিকাগুলি পরিচালনার জন্য বিশেষত উপযোগী (বিভাগ 5.2.3 দেখুন)। প্রতিটি তালিকা থ্রেড-নিরাপদ, এবং একের সাথে অন্যের রাজ্যের সংযোজনে কোনও বাধা নেই বলে VisualComponentএর থ্রেড সুরক্ষা দায়িত্ব অন্তর্নিহিত mouseListenersএবং keyListenersঅবজেক্টগুলিকে অর্পণ করতে পারে।
4.3.3। ডেলিগেশন ব্যর্থ হলে
বেশিরভাগ যৌগিক শ্রেণিগুলির মতো সহজ নয় VisualComponent: তাদের আক্রমণকারী থাকে যা তাদের উপাদান রাষ্ট্রের পরিবর্তনশীলগুলির সাথে সম্পর্কিত। NumberRangeতালিকাতে 4.10 AtomicIntegersএর রাজ্য পরিচালনা করতে দুটি ব্যবহার করে , তবে একটি অতিরিক্ত বাধা আরোপ করে - প্রথম সংখ্যাটি দ্বিতীয়টির চেয়ে কম বা সমান।
তালিকা 4.10। সংখ্যা পরিসীমা শ্রেণি যা এর আক্রমণকারীদের পর্যাপ্তরূপে রক্ষা করে না। এটি করবেন না।
public class NumberRange {
// INVARIANT: lower <= upper
private final AtomicInteger lower = new AtomicInteger(0);
private final AtomicInteger upper = new AtomicInteger(0);
public void setLower(int i) {
//Warning - unsafe check-then-act
if(i > upper.get()) {
throw new IllegalArgumentException(
"Can't set lower to " + i + " > upper ");
}
lower.set(i);
}
public void setUpper(int i) {
//Warning - unsafe check-then-act
if(i < lower.get()) {
throw new IllegalArgumentException(
"Can't set upper to " + i + " < lower ");
}
upper.set(i);
}
public boolean isInRange(int i){
return (i >= lower.get() && i <= upper.get());
}
}
NumberRangeহয় থ্রেড-নিরাপদ নয় ; এটি আক্রমণকারীকে সংরক্ষণ করে না যা নিম্ন এবং উচ্চতরকে সীমাবদ্ধ করে। setLowerএবং setUpperপদ্ধতি এই পরিবর্তিত সম্মান করার প্রচেষ্টা, কিন্তু দুর্বল না। উভয় setLowerএবং setUpperচেক-তৎকালীন অ্যাক্ট সিকোয়েন্সগুলি হয় তবে তারা এটিকে পারমাণবিক করতে পর্যাপ্ত লকিং ব্যবহার করে না। যদি সংখ্যা পরিসীমা হ'ল (0, 10), এবং একটি থ্রেড কল করার setLower(5)সময় অন্য থ্রেড কল করবে setUpper(4), কিছু অশুভ সময় দেওয়ার সাথে সাথে উভয়ই সেটারগুলিতে চেকগুলি পাস করবে এবং উভয় পরিবর্তন প্রয়োগ করা হবে। ফলাফলটি এখন পরিসরটি ধরে রাখে (5, 4) - একটি অবৈধ রাষ্ট্র । সুতরাং অন্তর্নিহিত অ্যাটমিকআইন্টিজারগুলি থ্রেড-নিরাপদ থাকা অবস্থায়, সম্মিলিত শ্রেণিটি নয় । কারণ অন্তর্নিহিত রাষ্ট্র পরিবর্তনশীল lowerএবংupperস্বতন্ত্র নয়, NumberRangeএটির থ্রেড-নিরাপদ রাষ্ট্র পরিবর্তনশীলগুলিতে কেবল থ্রেড সুরক্ষা প্রদান করতে পারে না cannot
NumberRangeএর আক্রমণকারীদের বজায় রাখতে লক ব্যবহার করে থ্রেড-সেফ তৈরি করা যেতে পারে, যেমন একটি সাধারণ লক দিয়ে নিম্ন এবং উপরের প্রহরী রক্ষা করা। ক্লায়েন্টদের আক্রমণকারীদের বিভক্ত করা থেকে বিরত রাখতে এটিকে নিম্ন এবং উচ্চতর প্রকাশ এড়াতে হবে।
যদি কোনও শ্রেণীর যৌগিক ক্রিয়াকলাপ থাকে, NumberRangeতবে, একা প্রতিনিধিরা আবার থ্রেড সুরক্ষার জন্য উপযুক্ত পদ্ধতি নয়। এই ক্ষেত্রে, যৌগিক ক্রিয়াগুলি পারমাণবিক কিনা তা নিশ্চিত করার জন্য শ্রেণিকে অবশ্যই তার নিজস্ব লকিং সরবরাহ করতে হবে, যদি না সম্পূর্ণ যৌগিক ক্রিয়াটি অন্তর্নিহিত রাষ্ট্রীয় ভেরিয়েবলগুলিতেও অর্পণ করা যায়।
যদি কোনও শ্রেণি একাধিক স্বতন্ত্র থ্রেড-নিরাপদ রাষ্ট্রের ভেরিয়েবলগুলির সমন্বয়ে গঠিত এবং এর কোনও অপারেশন নেই যার কোনও অবৈধ রাষ্ট্র রূপান্তর রয়েছে, তবে এটি থ্রেড সুরক্ষা অন্তর্নিহিত রাষ্ট্রের ভেরিয়েবলগুলিতে প্রেরণ করতে পারে।