JavaRush /جاوا بلاگ /Random-UR /کافی وقفہ نمبر 165۔ جاوا میں پیکجز۔ ابتدائیوں کے لیے تھری...

کافی وقفہ نمبر 165۔ جاوا میں پیکجز۔ ابتدائیوں کے لیے تھریڈ سے محفوظ طریقے

گروپ میں شائع ہوا۔

جاوا پیکجز

ماخذ: Usemynotes یہ پوسٹ آپ کو جاوا میں پیکجز کو بہتر طور پر سمجھنے، ان کے مقصد اور ان کو لاگو کرنے کے طریقہ کو سمجھنے میں مدد کرے گی۔ کافی وقفہ نمبر 165۔  جاوا میں پیکجز۔  ابتدائیوں کے لیے تھریڈ سے محفوظ طریقے - 1

جاوا میں پیکجز کیا ہیں؟

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

جاوا میں پیکجوں کی کچھ اقسام:

  • java.lang - پہلے سے طے شدہ جاوا کے ساتھ بنڈل آتا ہے۔
  • java.io - ان پٹ/آؤٹ پٹ سے متعلق کلاسز، طریقے اور دیگر عناصر پر مشتمل ہے۔

پیکجز کی ضرورت کیوں ہے؟

  • نام کے تنازعات سے بچنے کے لیے۔
  • کنٹرول رسائی فراہم کرنے کے لیے۔
  • ڈیٹا انکیپسولیشن حاصل کرنے کے لیے۔

جاوا میں پیکج کیسے بنایا جائے؟

آئیے کمپیوٹر کے نام سے ایک پیکیج بنائیں ۔ عام طور پر پیکیج کا نام چھوٹے حروف میں لکھا جاتا ہے۔ یہ صرف کلاس کے ناموں کے ساتھ نام کے تنازعات سے بچنے کے لیے کیا جاتا ہے۔ ہم پلگ ایبل نامی ایک انٹرفیس بھی بنائیں گے ، جو کمپیوٹر پیکج میں موجود ہوگا ۔
package computer;

interface Pluggable {
   public void pluggedIn();
   public void pluggedOut();
}
اب ہم PenDrive کے نام سے ایک کلاس بنائیں گے جو اوپر والے انٹرفیس کو نافذ کرے گی۔
package computer;

public class PenDrive implements Pluggable {

   int storage = 64;

   public void pluggedIn () {
     System.out.println("Pen Drive is connected");
   }

   public void pluggedOut () {
     System.out.println("Pen Drive is removed");
   }

   public int storage() {
     return storage;
   }

   public static void main(String args[]) {
     PenDrive p = new PenDrive ();
     p.pluggedIn();
     System.out.println("Pen Drive Storage: " + p.storage());
     p.pluggedOut();
   }
}

جاوا میں پیکیج کا درجہ بندی کیسے بنائیں؟

درجہ بندی بناتے وقت، جاوا میں پیکجوں کا نام الٹ ترتیب میں رکھا جاتا ہے۔ یہ انہیں ڈائریکٹریز یا فولڈرز سے بہت ملتا جلتا بناتا ہے۔ بالکل اسی طرح جیسے پرسنل کمپیوٹر پر، جہاں ایک فولڈر میں ایک یا زیادہ ذیلی فولڈر ہو سکتے ہیں، یہی جاوا میں پیکجوں پر لاگو ہوتا ہے۔ آئیے Asia.India.Kolkata کے نام سے ایک پیکج دیکھتے ہیں ۔ یہ سب موجودہ فولڈرز ہیں، لیکن اگر آپ جغرافیہ پر غور کریں تو یہ واضح ہے کہ کلکتہ ہندوستان میں ہے، اور ہندوستان ایشیا میں ہے۔ درجہ بندی کا بنیادی مقصد کلاسز کو تلاش کرنا آسان بنانا ہے۔

جاوا میں پیکجوں کی اقسام

بلٹ ان پیکجز

بلٹ ان پیکجز وہ پیکجز ہیں جن میں بلٹ ان کلاسز کی ایک بڑی تعداد ہوتی ہے جو Java API کا حصہ ہیں۔ ان پیکجوں میں شامل ہیں:
  • java.util - یہ پیکج یوٹیلیٹی کلاسز کی ایک محدود تعداد پر مشتمل ہے جو ڈیٹا سٹرکچر جیسے لنکڈ لسٹ، سیٹس وغیرہ کو لاگو کرنے کے لیے استعمال ہوتے ہیں۔ یہ تاریخ اور وقت کی کارروائیوں اور بہت کچھ کی بھی حمایت کرتا ہے۔
  • java.net - اس میں نیٹ ورک آپریشنز کے لیے استعمال ہونے والی کلاسز شامل ہیں۔

صارف کی وضاحت کردہ پیکیجز

صارف کے ذریعہ بیان کردہ پیکیجز کو صارف پیکیج کہا جاتا ہے۔ صارف دستی طور پر ایک پیکیج بنا سکتا ہے اور اس میں جتنی کلاسز چاہیں رکھ سکتا ہے۔

دوسرے پیکج سے پیکج تک کیسے رسائی حاصل کی جائے؟

آپ کسی دوسرے پیکج سے تین آسان طریقوں سے پیکیج تک رسائی حاصل کر سکتے ہیں:
  • درآمدی بیان میں نجمہ کا استعمال
جاوا میں "سب چیزوں" کی نمائندگی کرنے کے لیے نجمہ ( * ) کردار استعمال ہوتا ہے۔ اس کا استعمال کرتے ہوئے، ہم ہر وہ چیز درآمد کر سکتے ہیں جو پیکیج کے ذیلی پیکیج کے اندر ہے۔ مثال: ٹولز نامی پیکج پر غور کریں ۔ اگر ہم اس پیکج کے اندر موجود ہر چیز کو درآمد کرنا چاہتے ہیں تو ہمیں امپورٹ اسٹیٹمنٹ کو استعمال کرنے کی ضرورت ہے جیسے:
import tools.*;
  • درآمد پیکیج کا استعمال کرتے ہوئے کلاس نام؛
پیکج میں کلاس کے نام کا ذکر کرنا آپ کے پروگرام میں صرف ان کلاسوں کو درآمد کرنے کا ایک مؤثر طریقہ ہے جس کی آپ کو ضرورت ہے، اس طرح غیر ضروری کلاسوں کو درآمد کرنے سے گریز کریں۔ مثال: کتابوں کے نام کے پیکیج پر غور کریں ۔ اگر ہم اس سے صرف ایک مخصوص کلاس یا انٹرفیس درآمد کرنا چاہتے ہیں (ہم صفحات کی کلاس کو دیکھیں گے )، تو ہم اسے استعمال کرکے درآمد کرسکتے ہیں:
import book.Pages;
  • اپنا پورا نام استعمال کرنا
جاوا پیکج یا اس کی کلاسز کو ان کے مکمل اہل نام کا استعمال کرکے براہ راست استعمال کرنے کا ایک طریقہ ہے۔ اس طرح آپ کو پیکیج درآمد کرنے کی ضرورت نہیں ہے اور آپ اسے براہ راست پروگرام میں استعمال کرسکتے ہیں۔ مثال:
java.awt.List aSimpleList = new java.awt.List();

جاوا میں پہلے سے طے شدہ بیچ کا سائز

پہلے سے طے شدہ طور پر، جاوا java.lang پیکیج کو درآمد کرتا ہے ۔ اس میں بہت سی کلاسیں ہیں جو عام طور پر سادہ جاوا پروگراموں جیسے String ، Integer اور دیگر میں استعمال ہوتی ہیں۔ سب سے اہم کلاسوں میں سے ایک آبجیکٹ کلاس ہے، جو کہ java.lang پیکیج میں بھی پائی جاتی ہے ۔ اس پیکیج کا سائز اس کے اجزاء پر مبنی ہے: 8 انٹرفیس، 37 کلاسز، 3 اینیمز، 27 مستثنیات، 23 غلطی کی اقسام، اور 5 تشریحی اقسام۔

ابتدائیوں کے لیے تھریڈ سے محفوظ جاوا کے طریقے

ماخذ: میڈیم اس مضمون کا استعمال کرتے ہوئے، آپ جاوا میں تھریڈ محفوظ طریقوں کے کام کے بارے میں جان سکتے ہیں۔ کافی وقفہ نمبر 165۔  جاوا میں پیکجز۔  ابتدائیوں کے لیے تھریڈ سے محفوظ طریقے - 2میں نے محسوس کیا ہے کہ بہت سے جونیئر/مڈل جاوا ڈویلپر غلط سمجھتے ہیں کہ اصلی پروجیکٹس میں تھریڈ سیف طریقوں کو کیسے کام کرنا چاہیے۔ اور چونکہ ہم عام طور پر ملٹی تھریڈڈ ماحول میں کام کرتے ہیں، اس لیے ان کا درست استعمال بہت ضروری ہے۔ تھریڈ سیف میتھڈ ایک ایسا طریقہ ہے جسے ایک دوسرے کے ڈیٹا سٹیٹ کو متاثر کیے بغیر بیک وقت متعدد تھریڈز سے کال کیا جا سکتا ہے۔ اس تصور کی ناکافی تفہیم ایسے کیڑوں کی طرف لے جاتی ہے جنہیں تلاش کرنا اور درست کرنا مشکل ہوتا ہے۔ ایسی غلطیوں سے بچنے کے لیے آئیے مثالوں پر نظر ڈالیں۔

مثال نمبر 1:

public static int countLetters(String input) {
    int counter = 0;

    for (Character c : input.toCharArray()) {
        if (Character.isAlphabetic(c)) {
            counter++;
        }
    }

    return counter;
}
  • کاؤنٹ لیٹرز کا طریقہ جامد ہے، یہ ایک int ویلیو واپس کرتا ہے اور سٹرنگ پیرامیٹر کو بطور ان پٹ قبول کرتا ہے۔
  • طریقہ کار کے اندر ایک پرائمیٹو ویری ایبل کاؤنٹر بنایا جاتا ہے، پھر لوپ ان پٹ سٹرنگ کے کریکٹرز سے گزرتا ہے اور جب بھی کسی لیٹر کریکٹر کا سامنا ہوتا ہے تو متغیر کاؤنٹر کو بڑھاتا ہے۔
کیا یہ طریقہ تھریڈ محفوظ ہے؟ بہت سے ڈویلپرز نہیں کہتے ہیں، کیونکہ اس معاملے میں ہمارے پاس انکریمنٹ آپریشن ہے، جو تھریڈ محفوظ نہیں ہے۔ آئیے اس کا پتہ لگائیں۔ جاوا میموری ماڈل میں ہمارے پاس اسٹیک اور ہیپ ہے۔ ہر تھریڈ کا اپنا اسٹیک ہوتا ہے، اور تمام تھریڈز ایک ہی ہیپ کا اشتراک کرتے ہیں۔ اس سلسلے میں، اسٹیک ڈیٹا ہمیشہ تھریڈ محفوظ ہوتا ہے، لیکن ہیپ ڈیٹا نہیں ہوتا ہے۔ اسٹیک قدیم چیزوں اور آبجیکٹ کے حوالہ جات کو محفوظ کرتا ہے۔ ڈھیر خود اشیاء پر مشتمل ہے۔ اس کا مطلب ہے کہ اس کوڈ کی مثال میں، ہر تھریڈ اسٹیک پر اپنے متغیر کاؤنٹر کو اسٹور کرتا ہے اور دوسرے تھریڈز کے ڈیٹا پر اس کا کوئی اثر نہیں ہوتا، اس لیے طریقہ thread safe ہے ۔ نوٹ کریں کہ سٹرنگ ان پٹ ویلیو بھی ایک آبجیکٹ ہے، لیکن سٹرنگ اور پرائمیٹو ریپرز ( Integer ، Long ، Double ، Boolean وغیرہ) تھریڈ محفوظ ہیں کیونکہ وہ ناقابل تغیر ہیں۔

مثال نمبر 2:

public static int countLetters2(String input) {
    List<Character> listCounter = new ArrayList<>();

    for (Character c : input.toCharArray()) {
        if (Character.isAlphabetic(c)) {
            listCounter.add(c);
        }
    }

    return listCounter.size();
}
اس کوڈ میں پہلی مثال کے طور پر وہی منطق استعمال کی گئی ہے، لیکن ایک قدیم int متغیر کی بجائے List آبجیکٹ کا استعمال کیا گیا ہے ۔ پچھلے حصے سے، ہم جانتے ہیں کہ جاوا میں اشیاء ہیپ پر محفوظ ہیں اور فہرست ایک آبجیکٹ ہے۔ ہم یہ بھی جانتے ہیں کہ اسٹیک ڈھیر پر موجود اشیاء کے حوالہ جات کو محفوظ کرتا ہے۔ مثال #2 میں، ہر تھریڈ ایک نیا ArrayList آبجیکٹ بناتا ہے : اور listCounter متغیر اپنے آبجیکٹ کا حوالہ ہیپ پر اسٹور کرتا ہے، اس لیے کوئی دوسرا تھریڈ اس آبجیکٹ کو تبدیل نہیں کرسکتا۔
List<Character> listCounter = new ArrayList<>();
اس کا مطلب ہے کہ یہ طریقہ تھریڈ سیف ہے۔

مثال نمبر 3:

public class CounterUtil { // singleton

    List<Character> listCounter = new ArrayList<>();

    public int countLetters3(String input) {
        for (Character c : input.toCharArray()) {
            if (Character.isAlphabetic(c)) {
                listCounter.add(c);
            }
        }

        return listCounter.size();
    }
}
اس مثال میں، ہمارے پاس ایک سنگلٹن (یہ اہم ہے) کلاس CounterUtil ہے جس میں عالمی متغیر listCounter ہے ۔ یہ متغیر سنگلٹن مثال کے طور پر ایک ہی وقت میں بنایا گیا ہے۔ جب متعدد تھریڈز کو کال کرتے ہیں countChars3 طریقہ ، وہ سب ایک ہی عالمی متغیر listCounter استعمال کرتے ہیں ، جو ہیپ پر ایک ہی چیز کا حوالہ محفوظ کرتا ہے، اور وہاں کے تھریڈز ایک دوسرے پر اثر انداز ہوں گے۔ لہذا ہم یہ نتیجہ اخذ کر سکتے ہیں کہ یہ طریقہ تھریڈ محفوظ نہیں ہے۔ اور یہاں تک کہ اگر ہم List<Character> listCounter کو ایک پرائمیٹو متغیر int counter میں تبدیل کرتے ہیں تو یہ بھی تھریڈ محفوظ نہیں ہوگا کیونکہ تمام تھریڈز ایک ہی قدیم متغیر کا استعمال کریں گے۔

آخری مثال:

public static int countLetters4(List<Character> inputList) {
    List<Character> listCounter = new ArrayList<>();

    for (Character c : inputList) {
        if (Character.isAlphabetic(c)) {
            listCounter.add(c);
        }
    }

    return listCounter.size();
}
CountLetters4 طریقہ String پیرامیٹر کے بجائے حروف کی فہرست کو قبول کرتا ہے ۔ یہاں ہم اس بات کی ضمانت نہیں دے سکتے کہ یہ طریقہ تھریڈ محفوظ ہے۔ کیوں؟ کیونکہ ہم اس بات کا یقین نہیں کر سکتے کہ ڈویلپر اس طریقہ کو کس طرح استعمال کریں گے۔ اگر باہر سے کوئی اور تھریڈ ان پٹ لسٹ میں ڈیٹا کو ہمارے counterLetters4 طریقہ کی طرح تبدیل کرتا ہے ، تو یہ حتمی نتیجہ کو متاثر کر سکتا ہے۔

نتیجہ

ہم نے صرف چار مثالوں کو دیکھا ہے، اور وہ جاوا پروجیکٹس میں تھریڈ سیفٹی کے تمام پہلوؤں کا احاطہ نہیں کرتے ہیں، لیکن یہ شروع کرنے کے لیے ایک اچھی جگہ ہیں۔ اگلی بار جب آپ اپنے کوڈ میں کوئی طریقہ دیکھیں تو اپنے آپ سے پوچھیں، "کیا یہ طریقہ تھریڈ محفوظ ہے؟" اور بہت جلد آپ اس کا جواب واضح طور پر سمجھ جائیں گے۔
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION