CodeGym /جاوا بلاگ /Random-UR /جاوا کور کے لیے سب سے اوپر 50 ملازمت کے انٹرویو کے سوالات...
John Squirrels
سطح
San Francisco

جاوا کور کے لیے سب سے اوپر 50 ملازمت کے انٹرویو کے سوالات اور جوابات۔ حصہ 2

گروپ میں شائع ہوا۔
جاوا کور کے لیے سب سے اوپر 50 ملازمت کے انٹرویو کے سوالات اور جوابات۔ حصہ 1 جاوا کور کے لیے سب سے اوپر 50 ملازمت کے انٹرویو کے سوالات اور جوابات۔  حصہ 2 - 1

ملٹی تھریڈنگ

24. میں جاوا میں نیا تھریڈ کیسے بنا سکتا ہوں؟

ایک یا دوسرے طریقے سے، تھریڈ کلاس کا استعمال کرتے ہوئے ایک تھریڈ بنایا جاتا ہے۔ لیکن ایسا کرنے کے مختلف طریقے ہیں…
  1. وارث java.lang.Thread _
  2. java.lang.Runnable انٹرفیس کو لاگو کریں - تھریڈ کلاس کا کنسٹرکٹر رن ایبل آبجیکٹ لیتا ہے۔
آئیے ان میں سے ہر ایک کے بارے میں بات کرتے ہیں۔

تھریڈ کلاس کا وارث بنیں۔

اس صورت میں، ہم اپنی کلاس کو وارث بناتے ہیں java.lang.Thread ۔ اس میں ایک run() طریقہ ہے، اور ہمیں بس یہی ضرورت ہے۔ نئے تھریڈ کی ساری زندگی اور منطق اسی طریقے میں ہو گی۔ یہ نئے تھریڈ کے لیے ایک اہم طریقہ کی طرح ہے ۔ اس کے بعد باقی رہ گیا اپنی کلاس کا ایک آبجیکٹ بنانا اور start() طریقہ کو کال کرنا ہے۔ یہ ایک نیا تھریڈ بنائے گا اور اس کی منطق پر عمل درآمد شروع کردے گا۔ آئیے ایک نظر ڈالتے ہیں:
/**
* An example of how to create threads by inheriting the {@link Thread} class.
*/
class ThreadInheritance extends Thread {

   @Override
   public void run() {
       System.out.println(Thread.currentThread().getName());
   }

   public static void main(String[] args) {
       ThreadInheritance threadInheritance1 = new ThreadInheritance();
       ThreadInheritance threadInheritance2 = new ThreadInheritance();
       ThreadInheritance threadInheritance3 = new ThreadInheritance();
       threadInheritance1.start();
       threadInheritance2.start();
       threadInheritance3.start();
   }
}
کنسول آؤٹ پٹ کچھ اس طرح ہوگا:
تھریڈ-1 تھریڈ-0 تھریڈ-2
یعنی، یہاں تک کہ ہم دیکھتے ہیں کہ تھریڈز کو ترتیب سے نہیں، بلکہ جیسا کہ JVM ان کو چلانے کے لیے موزوں سمجھتا ہے:)

رن ایبل انٹرفیس کو لاگو کریں۔

اگر آپ وراثت کے خلاف ہیں اور/یا پہلے ہی کسی دوسری کلاس کے وارث ہیں، تو آپ java.lang.Runnable انٹرفیس استعمال کر سکتے ہیں۔ یہاں، ہم اپنی کلاس کو اس انٹرفیس کو نافذ کرتے ہوئے run() طریقہ کو نافذ کرتے ہیں ، جیسا کہ اوپر کی مثال میں ہے۔ باقی رہ گیا ہے Thread آبجیکٹ بنانا ۔ ایسا لگتا ہے کہ کوڈ کی مزید لائنیں بدتر ہیں۔ لیکن ہم جانتے ہیں کہ وراثت کتنی نقصان دہ ہے اور یہ کہ ہر طرح سے اس سے بچنا ہی بہتر ہے؛) ایک نظر ڈالیں:
/**
* An example of how to create threads from the {@link Runnable} interface.
* It's easier than easy — we implement this interface and then pass an instance of our object
* to the constructor.
*/
class ThreadInheritance implements Runnable {

   @Override
   public void run() {
       System.out.println(Thread.currentThread().getName());
   }

   public static void main(String[] args) {
       ThreadInheritance runnable1 = new ThreadInheritance();
       ThreadInheritance runnable2 = new ThreadInheritance();
       ThreadInheritance runnable3 = new ThreadInheritance();

       Thread threadRunnable1 = new Thread(runnable1);
       Thread threadRunnable2 = new Thread(runnable2);
       Thread threadRunnable3 = new Thread(runnable3);

       threadRunnable1.start();
       threadRunnable2.start();
       threadRunnable3.start();
   }
}
اور یہاں نتیجہ ہے:
تھریڈ-0 تھریڈ-1 تھریڈ-2

25. عمل اور دھاگے میں کیا فرق ہے؟

جاوا کور کے لیے سب سے اوپر 50 ملازمت کے انٹرویو کے سوالات اور جوابات۔  حصہ 2 - 2ایک عمل اور ایک دھاگہ درج ذیل طریقوں سے مختلف ہیں:
  1. ایک چلنے والے پروگرام کو ایک عمل کہا جاتا ہے، لیکن ایک دھاگہ ایک عمل کا ایک ٹکڑا ہے۔
  2. عمل خود مختار ہیں، لیکن دھاگے ایک عمل کے ٹکڑے ہیں۔
  3. پروسیسز کے پاس میموری میں مختلف ایڈریس اسپیس ہوتے ہیں، لیکن تھریڈز ایک مشترکہ ایڈریس اسپیس کا اشتراک کرتے ہیں۔
  4. دھاگوں کے درمیان سیاق و سباق کی تبدیلی عمل کے درمیان سوئچنگ سے زیادہ تیز ہے۔
  5. انٹر پروسیس کمیونیکیشن انٹر تھریڈ کمیونیکیشن سے سست اور مہنگا ہے۔
  6. والدین کے عمل میں کوئی بھی تبدیلی بچے کے عمل کو متاثر نہیں کرتی ہے، لیکن پیرنٹ تھریڈ میں تبدیلیاں بچوں کے دھاگے کو متاثر کر سکتی ہیں۔

26. ملٹی تھریڈنگ کے کیا فوائد ہیں؟

  1. ملٹی تھریڈنگ ایک ایپلیکیشن/پروگرام کو ہمیشہ ان پٹ کے لیے جوابدہ رہنے کی اجازت دیتی ہے، چاہے وہ پہلے سے ہی کچھ بیک گراؤنڈ ٹاسک چلا رہا ہو۔
  2. ملٹی تھریڈنگ کاموں کو تیزی سے مکمل کرنا ممکن بناتی ہے، کیونکہ تھریڈز آزادانہ طور پر چلتے ہیں۔
  3. ملٹی تھریڈنگ کیش میموری کا بہتر استعمال فراہم کرتی ہے، کیونکہ تھریڈز مشترکہ میموری وسائل تک رسائی حاصل کر سکتے ہیں۔
  4. ملٹی تھریڈنگ مطلوبہ سرورز کی تعداد کو کم کرتی ہے، کیونکہ ایک سرور بیک وقت متعدد تھریڈز چلا سکتا ہے۔

27. ایک دھاگے کی زندگی کے چکر میں کیا ریاستیں ہیں؟

جاوا کور کے لیے سب سے اوپر 50 ملازمت کے انٹرویو کے سوالات اور جوابات۔  حصہ 2 - 3
  1. نیا: اس حالت میں، تھریڈ آبجیکٹ نئے آپریٹر کا استعمال کرتے ہوئے بنایا گیا ہے، لیکن ایک نیا تھریڈ ابھی تک موجود نہیں ہے۔ تھریڈ اس وقت تک شروع نہیں ہوتا جب تک کہ ہم start() طریقہ کو کال نہ کریں۔
  2. چلانے کے قابل: اس حالت میں، دھاگہ start() کے بعد چلنے کے لیے تیار ہے۔ طریقہ کہا جاتا ہے. تاہم، یہ ابھی تک تھریڈ شیڈولر کی طرف سے منتخب نہیں کیا گیا ہے.
  3. چل رہا ہے: اس حالت میں، تھریڈ شیڈولر تیار حالت سے ایک دھاگہ چنتا ہے، اور یہ چلتا ہے۔
  4. انتظار/مسدود: اس حالت میں، ایک تھریڈ نہیں چل رہا ہے، لیکن یہ ابھی تک زندہ ہے یا کسی اور تھریڈ کے مکمل ہونے کا انتظار کر رہا ہے۔
  5. ڈیڈ/ٹرمینیٹڈ: جب کوئی تھریڈ رن() طریقہ سے باہر نکلتا ہے تو یہ مردہ یا ختم شدہ حالت میں ہوتا ہے۔

28. کیا ایک تھریڈ کو دو بار چلانا ممکن ہے؟

نہیں، ہم تھریڈ کو دوبارہ شروع نہیں کر سکتے، کیونکہ تھریڈ شروع ہونے اور چلنے کے بعد، یہ مردہ حالت میں چلا جاتا ہے۔ اگر ہم دو بار تھریڈ شروع کرنے کی کوشش کرتے ہیں تو java.lang.IllegalThreadStateException پھینک دیا جائے گا۔ آئیے ایک نظر ڈالتے ہیں:
class DoubleStartThreadExample extends Thread {

   /**
    * Simulate the work of a thread
    */
   public void run() {
	// Something happens. At this state, this is not essential.
   }

   /**
    * Start the thread twice
    */
   public static void main(String[] args) {
       DoubleStartThreadExample doubleStartThreadExample = new DoubleStartThreadExample();
       doubleStartThreadExample.start();
       doubleStartThreadExample.start();
   }
}
جیسے ہی اسی تھریڈ کے دوسرے سٹارٹ پر پھانسی آئے گی ایک استثناء ہوگا۔ اسے خود آزمائیں؛) اس کے بارے میں سو بار سننے سے بہتر ہے کہ اسے ایک بار دیکھیں۔

29. اگر آپ start() کو کال کیے بغیر براہ راست run() کو کال کریں تو کیا ہوگا؟

ہاں، آپ یقینی طور پر run() طریقہ کو کال کرسکتے ہیں، لیکن ایک نیا تھریڈ نہیں بنایا جائے گا، اور طریقہ الگ تھریڈ پر نہیں چلے گا۔ اس صورت میں، ہمارے پاس ایک عام چیز ہے جسے ایک عام طریقہ کہتے ہیں۔ اگر ہم start() طریقہ کے بارے میں بات کر رہے ہیں، تو یہ اور بات ہے۔ جب یہ طریقہ کہا جاتا ہے، JVM ایک نیا دھاگہ شروع کرتا ہے۔ یہ تھریڈ، بدلے میں، ہمارا طریقہ کہتا ہے؛) یقین نہیں آتا؟ یہاں، اسے آزمائیں:
class ThreadCallRunExample extends Thread {

   public void run() {
       for (int i = 0; i < 5; i++) {
           System.out.print(i);
       }
   }

   public static void main(String args[]) {
       ThreadCallRunExample runExample1 = new ThreadCallRunExample();
       ThreadCallRunExample runExample2 = new ThreadCallRunExample();

       // Two ordinary methods will be called in the main thread, one after the other.
       runExample1.run();
       runExample2.run();
   }
}
اور کنسول آؤٹ پٹ اس طرح نظر آئے گا:
0123401234
جیسا کہ آپ دیکھ سکتے ہیں، کوئی دھاگہ نہیں بنایا گیا تھا۔ سب کچھ بالکل عام کلاس کی طرح کام کرتا تھا۔ سب سے پہلے، پہلی چیز کا طریقہ عمل کیا گیا تھا، اور پھر دوسرا.

30. ڈیمون تھریڈ کیا ہے؟

ڈیمون تھریڈ ایک تھریڈ ہے جو دوسرے تھریڈ کے مقابلے میں کم ترجیح پر کام کرتا ہے۔ دوسرے لفظوں میں، اس کا کام معاون کاموں کو انجام دینا ہے جو صرف دوسرے (اہم) دھاگے کے ساتھ مل کر کرنے کی ضرورت ہے۔ بہت سے ڈیمون تھریڈز ہیں جو خود بخود چلتے ہیں، جیسے کوڑا اٹھانا، فائنلائزر وغیرہ۔

جاوا ڈیمون تھریڈ کو کیوں ختم کرتا ہے؟

ڈیمون تھریڈ کا واحد مقصد صارف کے تھریڈ کو بیک گراؤنڈ سپورٹ فراہم کرنا ہے۔ اس کے مطابق، اگر مین تھریڈ کو ختم کر دیا جاتا ہے، تو JVM خود بخود اپنے تمام ڈیمون تھریڈز کو ختم کر دیتا ہے۔

تھریڈ کلاس کے طریقے

java.lang.Thread کلاس ڈیمون تھریڈ کے ساتھ کام کرنے کے دو طریقے فراہم کرتی ہے :
  1. public void setDaemon(boolean status) — یہ طریقہ بتاتا ہے کہ آیا یہ ڈیمون تھریڈ ہو گا۔ پہلے سے طے شدہ غلط ہے ۔ اس کا مطلب یہ ہے کہ کوئی ڈیمون تھریڈز نہیں بنائے جائیں گے جب تک کہ آپ خاص طور پر ایسا نہیں کہتے ہیں۔
  2. public boolean isDaemon() — یہ طریقہ بنیادی طور پر ڈیمون متغیر کے لیے ایک گیٹر ہے، جسے ہم نے پچھلے طریقہ کا استعمال کرتے ہوئے سیٹ کیا ہے۔
مثال:
class DaemonThreadExample extends Thread {

   public void run() {
       // Checks whether this thread is a daemon
       if (Thread.currentThread().isDaemon()) {
           System.out.println("daemon thread");
       } else {
           System.out.println("user thread");
       }
   }

   public static void main(String[] args) {
       DaemonThreadExample thread1 = new DaemonThreadExample();
       DaemonThreadExample thread2 = new DaemonThreadExample();
       DaemonThreadExample thread3 = new DaemonThreadExample();

       // Make thread1 a daemon thread.
       thread1.setDaemon(true);

       System.out.println("daemon? " + thread1.isDaemon());
       System.out.println("daemon? " + thread2.isDaemon());
       System.out.println("daemon? " + thread3.isDaemon());

       thread1.start();
       thread2.start();
       thread3.start();
   }
}
کنسول آؤٹ پٹ:
ڈیمون حقیقی ڈیمون؟ جھوٹے ڈیمون؟ جھوٹے ڈیمون تھریڈ یوزر تھریڈ یوزر تھریڈ
آؤٹ پٹ سے، ہم دیکھتے ہیں کہ تھریڈ کے اندر، ہم static currentThread() طریقہ استعمال کر کے یہ معلوم کر سکتے ہیں کہ یہ کون سا تھریڈ ہے۔ متبادل طور پر، اگر ہمارے پاس تھریڈ آبجیکٹ کا حوالہ ہے، تو ہم اس سے بھی براہ راست معلوم کر سکتے ہیں۔ یہ ترتیب کی ضروری سطح فراہم کرتا ہے۔

31. کیا دھاگے کے بننے کے بعد اسے ڈیمون بنانا ممکن ہے؟

نہیں اگر آپ ایسا کرنے کی کوشش کرتے ہیں تو آپ کو ایک IllegalThreadStateException ملے گا ۔ اس کا مطلب ہے کہ ہم صرف ڈیمون تھریڈ شروع ہونے سے پہلے ہی بنا سکتے ہیں۔ مثال:
class SetDaemonAfterStartExample extends Thread {

   public void run() {
       System.out.println("Working...");
   }

   public static void main(String[] args) {
       SetDaemonAfterStartExample afterStartExample = new SetDaemonAfterStartExample();
       afterStartExample.start();

       // An exception will be thrown here
       afterStartExample.setDaemon(true);
   }
}
کنسول آؤٹ پٹ:
کام...

32. شٹ ڈاؤن ہک کیا ہے؟

شٹ ڈاؤن ہک ایک تھریڈ ہے جو جاوا ورچوئل مشین (JVM) کے بند ہونے سے پہلے واضح طور پر بلایا جاتا ہے۔ اس طرح، جب جاوا ورچوئل مشین عام طور پر یا غیر معمولی طور پر بند ہو جاتی ہے تو ہم اسے وسائل جاری کرنے یا حالت بچانے کے لیے استعمال کر سکتے ہیں۔ ہم مندرجہ ذیل طریقہ کا استعمال کرتے ہوئے ایک شٹ ڈاؤن ہک شامل کر سکتے ہیں:
Runtime.getRuntime().addShutdownHook(new ShutdownHookThreadExample());
جیسا کہ مثال میں دکھایا گیا ہے:
/**
* A program that shows how to start a shutdown hook thread,
* which will be executed right before the JVM shuts down
*/
class ShutdownHookThreadExample extends Thread {

   public void run() {
       System.out.println("shutdown hook executed");
   }

   public static void main(String[] args) {

       Runtime.getRuntime().addShutdownHook(new ShutdownHookThreadExample());

       System.out.println("Now the program is going to fall asleep. Press Ctrl+C to terminate it.");
       try {
           Thread.sleep(60000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }
}
کنسول آؤٹ پٹ:
اب پروگرام سو جانے والا ہے۔ اسے ختم کرنے کے لیے Ctrl+C دبائیں۔ شٹ ڈاؤن ہک کو پھانسی دی گئی۔

33. ہم آہنگی کیا ہے؟

جاوا میں، مطابقت پذیری کسی بھی مشترکہ وسائل تک متعدد تھریڈز کی رسائی کو کنٹرول کرنے کی صلاحیت ہے۔ جب متعدد تھریڈز ایک ہی کام کو بیک وقت انجام دینے کی کوشش کرتے ہیں، تو آپ کو غلط نتیجہ مل سکتا ہے۔ اس مسئلے کو حل کرنے کے لیے، جاوا مطابقت پذیری کا استعمال کرتا ہے، جو ایک وقت میں صرف ایک تھریڈ کو چلانے کی اجازت دیتا ہے۔ ہم آہنگی تین طریقوں سے حاصل کی جا سکتی ہے:
  • ایک طریقہ کو ہم وقت ساز کرنا
  • ایک مخصوص بلاک کو ہم وقت ساز کرنا
  • جامد مطابقت پذیری

ایک طریقہ کو ہم وقت ساز کرنا

کسی بھی مشترکہ وسائل کے لیے کسی چیز کو مقفل کرنے کے لیے ایک مطابقت پذیر طریقہ استعمال کیا جاتا ہے۔ جب کوئی تھریڈ ایک مطابقت پذیر طریقہ کو کال کرتا ہے، تو یہ خود بخود آبجیکٹ کا لاک حاصل کر لیتا ہے اور جب تھریڈ اپنا کام مکمل کر لیتا ہے تو اسے جاری کر دیتا ہے۔ یہ کام کرنے کے لیے، آپ کو مطابقت پذیر کلیدی لفظ شامل کرنے کی ضرورت ہے۔ ہم ایک مثال کو دیکھ کر دیکھ سکتے ہیں کہ یہ کیسے کام کرتا ہے:
/**
* An example where we synchronize a method. That is, we add the synchronized keyword to it.
* There are two authors who want to use one printer. Each of them has composed their own poems
* And of course they don’t want their poems mixed up. Instead, they want work to be performed in * * * order for each of them
*/
class Printer {

   synchronized void print(List<String> wordsToPrint) {
       wordsToPrint.forEach(System.out::print);
       System.out.println();
   }

   public static void main(String args[]) {
       // One object for two threads
       Printer printer  = new Printer();

       // Create two threads
       Writer1 writer1 = new Writer1(printer);
       Writer2 writer2 = new Writer2(printer);

       // Start them
       writer1.start();
       writer2.start();
   }
}

/**
* Author No. 1, who writes an original poem.
*/
class Writer1 extends Thread {
   Printer printer;

   Writer1(Printer printer) {
       this.printer = printer;
   }

   public void run() {
       List<string> poem = Arrays.asList("I ", this.getName(), " Write", " A Letter");
       printer.print(poem);
   }

}

/**
* Author No. 2, who writes an original poem.
*/
class Writer2 extends Thread {
   Printer printer;

   Writer2(Printer printer) {
       this.printer = printer;
   }

   public void run() {
       List<String> poem = Arrays.asList("I Do Not ", this.getName(), " Not Write", " No Letter");
       printer.print(poem);
   }
}
اور کنسول آؤٹ پٹ یہ ہے:
I Thread-0 Write A Letter I Do not Thread-1 Not Write No Letter

ہم وقت سازی بلاک

ایک مطابقت پذیر بلاک کو کسی طریقہ میں کسی خاص وسائل پر مطابقت پذیری انجام دینے کے لیے استعمال کیا جا سکتا ہے۔ آئیے کہتے ہیں کہ ایک بڑے طریقہ میں (ہاں، آپ کو انہیں نہیں لکھنا چاہئے، لیکن بعض اوقات ایسا ہوتا ہے) آپ کو کسی وجہ سے صرف ایک چھوٹے حصے کو ہم آہنگ کرنے کی ضرورت ہے۔ اگر آپ طریقہ کار کے تمام کوڈ کو مطابقت پذیر بلاک میں ڈالتے ہیں، تو یہ ایک مطابقت پذیر طریقہ کی طرح کام کرے گا۔ نحو اس طرح لگتا ہے:
synchronized ("object to be locked") {
   // The code that must be protected
}
پچھلی مثال کو دہرانے سے بچنے کے لیے، ہم گمنام کلاسز کا استعمال کرتے ہوئے تھریڈز بنائیں گے، یعنی ہم فوری طور پر رن ​​ایبل انٹرفیس کو نافذ کریں گے۔
/**
* This is how a synchronization block is added.
* Inside the block, you need to specify which object's mutex will be acquired.
*/
class Printer {

   void print(List<String> wordsToPrint) {
       synchronized (this) {
           wordsToPrint.forEach(System.out::print);
       }
       System.out.println();
   }

   public static void main(String args[]) {
       // One object for two threads
       Printer printer = new Printer();

       // Create two threads
       Thread writer1 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("I ", "Writer1", " Write", " A Letter");
               printer.print(poem);
           }
       });
       Thread writer2 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("I Do Not ", "Writer2", " Not Write", " No Letter");
               printer.print(poem);
           }
       });

       // Start them
       writer1.start();
       writer2.start();
   }
}

}
اور کنسول آؤٹ پٹ یہ ہے:
میں لکھنے والا 1 ایک خط لکھوں میں نہیں لکھتا 2 کوئی خط نہیں لکھتا

جامد مطابقت پذیری

اگر آپ ایک جامد طریقہ کو مطابقت پذیر بناتے ہیں، تو لاکنگ کلاس پر ہوگی، آبجیکٹ پر نہیں۔ اس مثال میں، ہم مطابقت پذیر مطلوبہ الفاظ کو جامد طریقہ پر لاگو کرکے جامد مطابقت پذیری انجام دیتے ہیں:
/**
* This is how a synchronization block is added.
* Inside the block, you need to specify which object's mutex will be acquired.
*/
class Printer {

   static synchronized void print(List<String> wordsToPrint) {
       wordsToPrint.forEach(System.out::print);
       System.out.println();
   }

   public static void main(String args[]) {

       // Create two threads
       Thread writer1 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("I ", "Writer1", " Write", " A Letter");
               Printer.print(poem);
           }
       });
       Thread writer2 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("I Do Not ", "Writer2", " Not Write", " No Letter");
               Printer.print(poem);
           }
       });

       // Start them
       writer1.start();
       writer2.start();
   }
}
اور کنسول آؤٹ پٹ یہ ہے:
میں نہیں لکھتا 2 کوئی خط نہیں لکھتا میں لکھنے والا1 خط لکھتا ہوں۔

34. ایک غیر مستحکم متغیر کیا ہے؟

ملٹی تھریڈ پروگرامنگ میں، غیر مستحکم کلیدی لفظ دھاگے کی حفاظت کے لیے استعمال ہوتا ہے۔ جب ایک متغیر متغیر میں ترمیم کی جاتی ہے، تو تبدیلی دیگر تمام دھاگوں پر نظر آتی ہے، لہذا ایک متغیر کو ایک وقت میں ایک تھریڈ کے ذریعے استعمال کیا جا سکتا ہے۔ غیر مستحکم مطلوبہ الفاظ کا استعمال کرتے ہوئے ، آپ اس بات کی ضمانت دے سکتے ہیں کہ متغیر تھریڈ سے محفوظ ہے اور مشترکہ میموری میں محفوظ ہے، اور یہ کہ تھریڈز اسے اپنے کیشز میں محفوظ نہیں کریں گے۔ یہ کیسا لگتا ہے؟
private volatile AtomicInteger count;
ہم صرف متغیر میں volatile شامل کرتے ہیں۔ لیکن ذہن میں رکھیں کہ اس کا مطلب مکمل دھاگے کی حفاظت نہیں ہے... آخر کار، متغیر پر کارروائیاں ایٹمی نہیں ہو سکتیں۔ اس نے کہا، آپ اٹامک کلاسز استعمال کر سکتے ہیں جو جوہری طور پر کام کرتی ہیں، یعنی ایک سی پی یو انسٹرکشن میں۔ java.util.concurrent.atomic پیکیج میں ایسی بہت سی کلاسیں ہیں ۔

35. تعطل کیا ہے؟

جاوا میں، تعطل ایک ایسی چیز ہے جو ملٹی تھریڈنگ کے حصے کے طور پر ہو سکتی ہے۔ تعطل اس وقت ہوسکتا ہے جب ایک تھریڈ کسی دوسرے دھاگے کے ذریعہ حاصل کردہ کسی چیز کے لاک کا انتظار کر رہا ہو، اور دوسرا دھاگہ پہلے دھاگے کے ذریعہ حاصل کردہ آبجیکٹ کے لاک کا انتظار کر رہا ہو۔ اس کا مطلب ہے کہ دونوں تھریڈز ایک دوسرے کا انتظار کر رہے ہیں، اور ان کے کوڈ پر عمل درآمد جاری نہیں رہ سکتا۔ جاوا کور کے لیے سب سے اوپر 50 ملازمت کے انٹرویو کے سوالات اور جوابات۔  حصہ 2 - 4آئیے ایک مثال پر غور کریں جس میں ایک کلاس ہے جو Runnable کو نافذ کرتی ہے۔ اس کا کنسٹرکٹر دو وسائل لیتا ہے۔ run() طریقہ ان کے لیے ترتیب میں تالا حاصل کرتا ہے۔ اگر آپ اس کلاس کی دو اشیاء بناتے ہیں، اور وسائل کو مختلف ترتیب سے پاس کرتے ہیں، تو آپ آسانی سے تعطل کا شکار ہو سکتے ہیں:
class DeadLock {

   public static void main(String[] args) {
       final Integer r1 = 10;
       final Integer r2 = 15;

       DeadlockThread threadR1R2 = new DeadlockThread(r1, r2);
       DeadlockThread threadR2R1 = new DeadlockThread(r2, r1);

       new Thread(threadR1R2).start();
       new Thread(threadR2R1).start();
   }
}

/**
* A class that accepts two resources.
*/
class DeadlockThread implements Runnable {

   private final Integer r1;
   private final Integer r2;

   public DeadlockThread(Integer r1, Integer r2) {
       this.r1 = r1;
       this.r2 = r2;
   }

   @Override
   public void run() {
       synchronized (r1) {
           System.out.println(Thread.currentThread().getName() + " acquired resource: " + r1);

           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }

           synchronized (r2) {
               System.out.println(Thread.currentThread().getName() + " acquired resource: " + r2);
           }
       }
   }
}
کنسول آؤٹ پٹ:
پہلے دھاگے نے پہلا وسیلہ حاصل کیا دوسرے دھاگے نے دوسرا وسیلہ حاصل کیا۔

36. آپ تعطل سے کیسے بچتے ہیں؟

چونکہ ہم جانتے ہیں کہ تعطل کیسے ہوتا ہے، ہم کچھ نتائج اخذ کر سکتے ہیں...
  • مندرجہ بالا مثال میں، تعطل اس حقیقت کی وجہ سے ہوتا ہے کہ ہمارے پاس نیسٹڈ لاکنگ ہے۔ یعنی، ہمارے پاس مطابقت پذیر بلاک کے اندر ایک مطابقت پذیر بلاک ہے۔ اس سے بچنے کے لیے، گھوںسلا بنانے کے بجائے، آپ کو ایک نئی اعلیٰ تجریدی پرت بنانے، مطابقت پذیری کو اعلیٰ سطح پر منتقل کرنے، اور نیسٹڈ لاکنگ کو ختم کرنے کی ضرورت ہے۔
  • آپ جتنا زیادہ لاکنگ کریں گے، اتنا ہی زیادہ امکان ہے کہ تعطل پیدا ہوگا۔ لہذا، ہر بار جب آپ مطابقت پذیر بلاک شامل کرتے ہیں، آپ کو یہ سوچنے کی ضرورت ہے کہ آیا آپ کو واقعی اس کی ضرورت ہے اور کیا آپ نیا بلاک شامل کرنے سے بچ سکتے ہیں۔
  • Thread.join() کا استعمال کرنا ۔ جب ایک تھریڈ دوسرے کا انتظار کر رہا ہو تو آپ تعطل کا شکار بھی ہو سکتے ہیں۔ اس مسئلے سے بچنے کے لیے، آپ join() طریقہ کے لیے ٹائم آؤٹ سیٹ کرنے پر غور کر سکتے ہیں ۔
  • اگر ہمارے پاس ایک دھاگہ ہے، تو کوئی تعطل نہیں ہوگا؛)

37. نسل کی شرط کیا ہے؟

اگر حقیقی زندگی کی ریسوں میں کاریں شامل ہوتی ہیں، تو ملٹی تھریڈنگ میں ریسوں میں دھاگے شامل ہوتے ہیں۔ لیکن کیوں؟ :/ دو تھریڈز ہیں جو چل رہے ہیں اور ایک ہی چیز تک رسائی حاصل کر سکتے ہیں۔ اور وہ ایک ہی وقت میں مشترکہ آبجیکٹ کی حالت کو اپ ڈیٹ کرنے کی کوشش کر سکتے ہیں۔ اب تک سب کچھ واضح ہے، ٹھیک ہے؟ دھاگوں کو یا تو لفظی طور پر متوازی طور پر (اگر پروسیسر میں ایک سے زیادہ کور ہے) یا ترتیب وار، پروسیسر کے درمیان وقفے وقفے سے وقت کے سلائسز مختص کیے جاتے ہیں۔ ہم ان عملوں کا انتظام نہیں کر سکتے۔ اس کا مطلب یہ ہے کہ جب ایک تھریڈ کسی آبجیکٹ سے ڈیٹا پڑھتا ہے تو ہم اس بات کی ضمانت نہیں دے سکتے کہ اس کے پاس کسی دوسرے تھریڈ کے ایسا کرنے سے پہلے آبجیکٹ کو تبدیل کرنے کا وقت ہوگا۔ اس طرح کے مسائل اس وقت پیدا ہوتے ہیں جب ہمارے پاس یہ "چیک اینڈ ایکٹ" کمبوز ہوتے ہیں۔ اس کا کیا مطلب ہے؟ فرض کریں کہ ہمارے پاس ایک if سٹیٹمنٹ ہے جس کا جسم if-condition خود بدلتا ہے، مثال کے طور پر:
int z = 0;

// Check
if (z < 5) {
// Act
   z = z + 5;
}
دو تھریڈز بیک وقت اس کوڈ بلاک میں داخل ہو سکتے ہیں جب z اب بھی صفر ہے اور پھر دونوں تھریڈز اس کی قدر کو تبدیل کر سکتے ہیں۔ نتیجے کے طور پر، ہمیں 5 کی متوقع قیمت نہیں ملے گی۔ اس کے بجائے، ہمیں 10 ملے گا۔ آپ اس سے کیسے بچیں گے؟ آپ کو چیک کرنے اور عمل کرنے سے پہلے ایک تالا حاصل کرنے کی ضرورت ہے، اور پھر اس کے بعد تالا کو جاری کرنا ہوگا۔ یعنی، آپ کو پہلے تھریڈ کو if بلاک میں داخل کرنے کی ضرورت ہے، تمام اعمال انجام دیں، z کو تبدیل کریں ، اور تب ہی اگلے تھریڈ کو بھی ایسا کرنے کا موقع دیں۔ لیکن اگلا تھریڈ if بلاک میں داخل نہیں ہوگا، کیونکہ z اب 5 ہوگا:
// Acquire the lock for z
if (z < 5) {
   z = z + 5;
}
// Release z's lock
===================================================

نتیجہ اخذ کرنے کے بجائے

میں ہر ایک کا شکریہ کہنا چاہتا ہوں جنہوں نے آخر تک پڑھا۔ یہ ایک طویل راستہ تھا، لیکن آپ نے برداشت کیا! شاید سب کچھ واضح نہیں ہے۔ یہ عام بات ہے۔ جب میں نے پہلی بار جاوا کا مطالعہ شروع کیا تو میں اپنے دماغ کو اس بات کے ارد گرد نہیں سمیٹ سکا کہ جامد متغیر کیا ہے۔ لیکن کوئی بڑی بات نہیں۔ میں اس پر سو گیا، چند اور مصرعے پڑھے، پھر سمجھ آگئی۔ انٹرویو کی تیاری عملی سوال کے بجائے ایک علمی سوال ہے۔ نتیجے کے طور پر، ہر انٹرویو سے پہلے، آپ کو ان چیزوں کا جائزہ لینا چاہیے اور اپنی یادداشت کو تازہ کرنا چاہیے جو آپ اکثر استعمال نہیں کرتے۔

اور ہمیشہ کی طرح، یہاں کچھ مفید لنکس ہیں:

پڑھنے کے لیے آپ سب کا شکریہ۔ جلد ہی ملتے ہیں :) میرا GitHub پروفائل جاوا کور کے لیے سب سے اوپر 50 ملازمت کے انٹرویو کے سوالات اور جوابات۔  حصہ 2 - 5
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION