CodeGym /جاوا بلاگ /Random-UR /ایک ساتھ بہتر: جاوا اور تھریڈ کلاس۔ حصہ VI - آگ دور!
John Squirrels
سطح
San Francisco

ایک ساتھ بہتر: جاوا اور تھریڈ کلاس۔ حصہ VI - آگ دور!

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

تعارف

دھاگے ایک دلچسپ چیز ہیں۔ گزشتہ جائزوں میں، ہم نے ملٹی تھریڈنگ کو لاگو کرنے کے لیے کچھ دستیاب ٹولز کو دیکھا۔ آئیے دیکھتے ہیں کہ ہم کیا دوسری دلچسپ چیزیں کر سکتے ہیں۔ اس وقت، ہم بہت کچھ جانتے ہیں. مثال کے طور پر، " بہتر ایک ساتھ: جاوا اور تھریڈ کلاس۔ حصہ اول — پھانسی کے دھاگوں " سے، ہم جانتے ہیں کہ تھریڈ کلاس عمل درآمد کے دھاگے کی نمائندگی کرتی ہے۔ ہم جانتے ہیں کہ تھریڈ کچھ کام انجام دیتا ہے۔ اگر ہم چاہتے ہیں کہ ہمارے کام اس قابل ہوں runتو ہمیں دھاگے کو نشان زد کرنا چاہیے Runnable۔ ایک ساتھ بہتر: جاوا اور تھریڈ کلاس۔  حصہ VI - آگ دور!  - 1یاد رکھنے کے لیے، ہم Tutorialspoint Online Java Compiler استعمال کر سکتے ہیں :
public static void main(String[] args){
	Runnable task = () -> {
 		Thread thread = Thread.currentThread();
		System.out.println("Hello from " + thread.getName());
	};
	Thread thread = new Thread(task);
	thread.start();
}
ہم یہ بھی جانتے ہیں کہ ہمارے پاس کوئی چیز ہے جسے تالا کہتے ہیں۔ ہم نے اس کے بارے میں " بہتر ایک ساتھ: جاوا اور تھریڈ کلاس۔ حصہ II - ہم آہنگی میں سیکھا ہے۔ اگر ایک تھریڈ لاک حاصل کرتا ہے، تو دوسرا تھریڈ جو لاک حاصل کرنے کی کوشش کر رہا ہے اسے لاک کے جاری ہونے کا انتظار کرنے پر مجبور کیا جائے گا:
import java.util.concurrent.locks.*;

public class HelloWorld{
	public static void main(String []args){
		Lock lock = new ReentrantLock();
		Runnable task = () -> {
			lock.lock();
			Thread thread = Thread.currentThread();
			System.out.println("Hello from " + thread.getName());
			lock.unlock();
		};
		Thread thread = new Thread(task);
		thread.start();
	}
}
میرے خیال میں اب وقت آگیا ہے کہ ہم اس کے بارے میں بات کریں کہ ہم کیا کر سکتے ہیں۔

سیمفورس

ایک ساتھ کتنے تھریڈز چل سکتے ہیں اس کو کنٹرول کرنے کا سب سے آسان طریقہ سیمفور ہے۔ یہ ریلوے سگنل کی طرح ہے۔ سبز کا مطلب ہے آگے بڑھنا۔ سرخ کا مطلب ہے انتظار کرنا۔ سیمفور سے کیا انتظار کریں؟ رسائی۔ رسائی حاصل کرنے کے لیے، ہمیں اسے حاصل کرنا ہوگا۔ اور جب رسائی کی مزید ضرورت نہیں ہے، تو ہمیں اسے دینا چاہیے یا اسے چھوڑ دینا چاہیے۔ آئیے دیکھتے ہیں کہ یہ کیسے کام کرتا ہے۔ ہمیں java.util.concurrent.Semaphoreکلاس درآمد کرنے کی ضرورت ہے۔ مثال:
public static void main(String[] args) throws InterruptedException {
	Semaphore semaphore = new Semaphore(0);
	Runnable task = () -> {
		try {
			semaphore.acquire();
			System.out.println("Finished");
			semaphore.release();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	};
	new Thread(task).start();
	Thread.sleep(5000);
	semaphore.release(1);
}
جیسا کہ آپ دیکھ سکتے ہیں، یہ آپریشنز (حاصل اور رہائی) ہمیں یہ سمجھنے میں مدد کرتے ہیں کہ سیمفور کیسے کام کرتا ہے۔ سب سے اہم بات یہ ہے کہ اگر ہمیں رسائی حاصل کرنی ہے تو سیمفور کے پاس اجازت نامے کی مثبت تعداد ہونی چاہیے۔ اس گنتی کو منفی نمبر پر شروع کیا جا سکتا ہے۔ اور ہم 1 سے زیادہ اجازت نامے کی درخواست کر سکتے ہیں۔

CountDownLatch

اگلا میکانزم ہے CountDownLatch۔ حیرت کی بات نہیں، یہ الٹی گنتی کے ساتھ ایک لیچ ہے۔ یہاں ہمیں کلاس کے لیے مناسب درآمدی بیان کی ضرورت ہے java.util.concurrent.CountDownLatch۔ یہ پاؤں کی دوڑ کی طرح ہے، جہاں ہر کوئی ابتدائی لائن پر جمع ہوتا ہے۔ اور ایک بار جب ہر کوئی تیار ہو جاتا ہے، سب کو ایک ہی وقت میں ابتدائی سگنل ملتا ہے اور بیک وقت شروع ہوتا ہے۔ مثال:
public static void main(String[] args) {
	CountDownLatch countDownLatch = new CountDownLatch(3);
	Runnable task = () -> {
		try {
			countDownLatch.countDown();
			System.out.println("Countdown: " + countDownLatch.getCount());
			countDownLatch.await();
			System.out.println("Finished");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	};
	for (int i = 0; i < 3; i++) {
		new Thread(task).start();
 	}
}
سب سے پہلے، ہم سب سے پہلے کنڈی کو بتاتے ہیں countDown()۔ گوگل الٹی گنتی کو "صفر کے الٹ ترتیب میں اعداد شمار کرنے کا عمل" کے طور پر بیان کرتا ہے۔ اور پھر ہم لیچ کو کہتے ہیں await()، یعنی کاؤنٹر کے صفر ہونے تک انتظار کریں۔ دلچسپ بات یہ ہے کہ یہ ایک بار کا کاؤنٹر ہے۔ جاوا دستاویزات میں کہا گیا ہے، "جب تھریڈز کو اس طرح بار بار گننا پڑتا ہے، اس کے بجائے سائکلک بیریر استعمال کریں"۔ دوسرے الفاظ میں، اگر آپ کو دوبارہ قابل استعمال کاؤنٹر کی ضرورت ہے، تو آپ کو ایک مختلف آپشن کی ضرورت ہے: CyclicBarrier۔

سائکلک بیریئر

جیسا کہ نام کا مطلب ہے، CyclicBarrierایک "دوبارہ قابل استعمال" رکاوٹ ہے۔ ہمیں کلاس درآمد کرنے کی ضرورت ہوگی java.util.concurrent.CyclicBarrier۔ آئیے ایک مثال دیکھتے ہیں:
public static void main(String[] args) throws InterruptedException {
	Runnable action = () -> System.out.println("On your mark!");
	CyclicBarrier barrier = new CyclicBarrier(3, action);
	Runnable task = () -> {
		try {
			barrier.await();
			System.out.println("Finished");
		} catch (BrokenBarrierException | InterruptedException e) {
			e.printStackTrace();
		}
	};
	System.out.println("Limit: " + barrier.getParties());
	for (int i = 0; i < 3; i++) {
		new Thread(task).start();
	}
}
جیسا کہ آپ دیکھ سکتے ہیں، تھریڈ awaitطریقہ چلاتا ہے، یعنی انتظار کرتا ہے۔ اس صورت میں، رکاوٹ کی قیمت کم ہو جاتی ہے. barrier.isBroken()جب الٹی گنتی صفر تک پہنچ جاتی ہے تو رکاوٹ کو ٹوٹا ہوا سمجھا جاتا ہے ( )۔ رکاوٹ کو دوبارہ ترتیب دینے کے لیے، آپ کو reset()طریقہ کار کو کال کرنے کی ضرورت ہے، جس CountDownLatchمیں نہیں ہے۔

ایکسچینجر

اگلا میکانزم ایکسچینجر ہے۔ اس تناظر میں، ایک ایکسچینج ایک مطابقت پذیری نقطہ ہے جہاں چیزوں کو تبدیل کیا جاتا ہے یا تبدیل کیا جاتا ہے. جیسا کہ آپ توقع کریں گے، ایک Exchangerایسی کلاس ہے جو تبادلہ یا تبادلہ کرتی ہے۔ آئیے سب سے آسان مثال دیکھیں:
public static void main(String[] args) {
	Exchanger<String> exchanger = new Exchanger<>();
	Runnable task = () -> {
		try {
			Thread thread = Thread.currentThread();
			String withThreadName = exchanger.exchange(thread.getName());
			System.out.println(thread.getName() + " exchanged with " + withThreadName);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	};
	new Thread(task).start();
	new Thread(task).start();
}
یہاں ہم دو تھریڈ شروع کرتے ہیں۔ ان میں سے ہر ایک تبادلے کا طریقہ چلاتا ہے اور دوسرے تھریڈ کا انتظار کرتا ہے کہ وہ تبادلے کا طریقہ بھی چلائے۔ ایسا کرنے میں، دھاگے گزرے ہوئے دلائل کا تبادلہ کرتے ہیں۔ دلچسپ کیا یہ آپ کو کچھ یاد نہیں دلاتا؟ یہ یاد دلاتا ہے SynchronousQueue، جو کہ کے دل میں ہے CachedThreadPool۔ وضاحت کے لیے، یہاں ایک مثال ہے:
public static void main(String[] args) throws InterruptedException {
	SynchronousQueue<String> queue = new SynchronousQueue<>();
	Runnable task = () -> {
		try {
			System.out.println(queue.take());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	};
	new Thread(task).start();
	queue.put("Message");
}
مثال سے پتہ چلتا ہے کہ جب نیا تھریڈ شروع ہوتا ہے، تو یہ انتظار کرے گا، کیونکہ قطار خالی ہو گی۔ اور پھر مین تھریڈ "پیغام" سٹرنگ کو قطار میں ڈال دیتا ہے۔ مزید یہ کہ یہ اس وقت تک رک جائے گا جب تک کہ یہ تار قطار سے موصول نہ ہوجائے۔ اس موضوع کے بارے میں مزید جاننے کے لیے آپ " SynchronousQueue vs Exchanger " بھی پڑھ سکتے ہیں۔

فیزر

ہم نے آخری کے لیے بہترین کو محفوظ کیا ہے Phaser۔ ہمیں کلاس درآمد کرنے کی ضرورت ہوگی java.util.concurrent.Phaser۔ آئیے ایک سادہ مثال دیکھیں:
public static void main(String[] args) throws InterruptedException {
        Phaser phaser = new Phaser();
        // By calling the register method, we register the current (main) thread as a party
        phaser.register();
        System.out.println("Phasecount is " + phaser.getPhase());
        testPhaser(phaser);
        testPhaser(phaser);
        testPhaser(phaser);
        // After 3 seconds, we arrive at the barrier and deregister. Number of arrivals = number of registrations = start
        Thread.sleep(3000);
        phaser.arriveAndDeregister();
        System.out.println("Phasecount is " + phaser.getPhase());
    }

    private static void testPhaser(final Phaser phaser) {
        // We indicate that there will be a +1 party on the Phaser
        phaser.register();
        // Start a new thread
        new Thread(() -> {
            String name = Thread.currentThread().getName();
            System.out.println(name + " arrived");
            phaser.arriveAndAwaitAdvance(); // The threads register arrival at the phaser.
            System.out.println(name + " after passing barrier");
        }).start();
    }
مثال یہ بتاتی ہے کہ استعمال کرتے وقت Phaser، رکاوٹ ٹوٹ جاتی ہے جب رجسٹریشن کی تعداد رکاوٹ پر آنے والوں کی تعداد سے ملتی ہے۔ آپ اس GeeksforGeeks مضمون Phaser کو پڑھ کر مزید واقف ہو سکتے ہیں ۔

خلاصہ

جیسا کہ آپ ان مثالوں سے دیکھ سکتے ہیں، تھریڈز کو سنکرونائز کرنے کے مختلف طریقے ہیں۔ اس سے پہلے، میں نے ملٹی تھریڈنگ کے پہلوؤں کو یاد کرنے کی کوشش کی۔ مجھے امید ہے کہ اس سیریز کی پچھلی قسطیں کارآمد تھیں۔ کچھ لوگ کہتے ہیں کہ ملٹی تھریڈنگ کا راستہ کتاب "جاوا کنکرنسی ان پریکٹس" سے شروع ہوتا ہے۔ اگرچہ یہ 2006 میں ریلیز ہوئی تھی، لیکن لوگ کہتے ہیں کہ یہ کتاب کافی بنیاد پر ہے اور آج بھی متعلقہ ہے۔ مثال کے طور پر، آپ یہاں بحث پڑھ سکتے ہیں: کیا "جاوا کنکرنسی ان پریکٹس" اب بھی درست ہے؟ . بحث میں لنکس کو پڑھنا بھی مفید ہے۔ مثال کے طور پر، کتاب The Well-Grounded Java Developer کا ایک لنک ہے ، اور ہم باب 4 کا خاص طور پر ذکر کریں گے۔ جدید کنکرنسی ۔ اس موضوع کے بارے میں ایک مکمل جائزہ بھی موجود ہے: کیا جاوا 8 کے دور میں "جاوا ہم آہنگی" اب بھی درست ہے؟ اس مضمون میں اس بارے میں تجاویز بھی دی گئی ہیں کہ اس موضوع کو صحیح معنوں میں سمجھنے کے لیے اور کیا پڑھا جائے۔ اس کے بعد، آپ OCA/OCP Java SE 8 پروگرامر پریکٹس ٹیسٹ جیسی بہترین کتاب پر ایک نظر ڈال سکتے ہیں ۔ ہمیں دوسرے مخفف میں دلچسپی ہے: OCP (Oracle Certified Professional)۔ آپ کو "باب 20: جاوا کنکرنسی" میں ٹیسٹ ملیں گے۔ اس کتاب میں وضاحت کے ساتھ سوالات اور جوابات دونوں ہیں۔ مثال کے طور پر: ایک ساتھ بہتر: جاوا اور تھریڈ کلاس۔  حصہ VI - آگ دور!  - 3بہت سے لوگ یہ کہنا شروع کر سکتے ہیں کہ یہ سوال طریقوں کے حفظ کی ایک اور مثال ہے۔ ایک طرف، ہاں۔ دوسری طرف، آپ اس سوال کا جواب یاد کر کے دے سکتے ہیں کہ یہ ExecutorServiceایک قسم کا "اپ گریڈ" ہے Executor۔ اور Executorاس کا مقصد صرف دھاگوں کی تخلیق کے طریقے کو چھپانا ہے، لیکن یہ ان پر عمل کرنے کا بنیادی طریقہ نہیں ہے، یعنی Runnableکسی نئے دھاگے پر کسی چیز کو شروع کرنا۔ اس لیے وہاں نہیں ہے execute(Callable)— کیونکہ میں ExecutorService، Executorصرف submit()ایسے طریقے شامل کرتا ہے جو کسی Futureچیز کو واپس کر سکتے ہیں۔ بلاشبہ، ہم طریقوں کی فہرست کو حفظ کر سکتے ہیں، لیکن کلاسوں کی نوعیت کے بارے میں ہمارے علم کی بنیاد پر اپنا جواب بنانا بہت آسان ہے۔ اور یہاں اس موضوع پر کچھ اضافی مواد ہیں: ایک ساتھ بہتر: جاوا اور تھریڈ کلاس۔ حصہ اول — عمل درآمد کے دھاگے ایک ساتھ بہتر: جاوا اور تھریڈ کلاس۔ حصہ دوم — ہم آہنگی ایک ساتھ بہتر: جاوا اور تھریڈ کلاس۔ حصہ III - ایک دوسرے کے ساتھ بہتر تعامل: جاوا اور تھریڈ کلاس۔ حصہ چہارم — کال کے قابل، مستقبل، اور دوست ایک ساتھ بہتر: جاوا اور تھریڈ کلاس۔ حصہ V — ایگزیکیوٹر، تھریڈ پول، فورک/جوائن
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION