JavaRush /جاوا بلاگ /Random-SD /توھان جاوا کي ھڪڙي سلسلي سان خراب نٿا ڪري سگھو: حصو VI - ...
Viacheslav
سطح

توھان جاوا کي ھڪڙي سلسلي سان خراب نٿا ڪري سگھو: حصو VI - رڪاوٽ ڏانھن!

گروپ ۾ شايع ٿيل

تعارف

وهڪرو هڪ دلچسپ شيء آهي. پوئين نظرثانين ۾، اسان ڏٺا ڪجھ دستياب اوزار ملٽي ٿريڊنگ کي لاڳو ڪرڻ لاءِ. اچو ته ڏسون ٻيون ڪهڙيون دلچسپ شيون اسان ڪري سگهون ٿا. هن موقعي تي اسان گهڻو ڪجهه ڄاڻون ٿا. مثال طور، " توهان جاوا کي هڪ موضوع سان خراب نه ٿا ڪري سگهو: حصو I - موضوع، " اسان ڄاڻون ٿا ته هڪ موضوع هڪ موضوع آهي. اسان ڄاڻون ٿا ته هڪ موضوع ڪجهه ڪم ڪري رهيو آهي. جيڪڏهن اسان چاهيون ٿا ته اسان جو ڪم هلائڻ جي قابل هجي ( run)، ته پوءِ اسان کي لازمي طور تي ٿريڊ کي مخصوص ڪرڻ گهرجي Runnable. توھان جاوا کي ھڪڙي سلسلي سان خراب نٿا ڪري سگھو: حصو VI - رڪاوٽ ڏانھن!  - 1ياد رکڻ لاءِ، اسان استعمال ڪري سگھون ٿا Tutorialspoint Java Online 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();
	}
}
منهنجو خيال آهي ته اهو وقت آهي انهي بابت ڳالهائڻ جو اسان ٻيو ڇا ڪري سگهون ٿا اهو دلچسپ آهي.

سيمفورس

هڪ ئي وقت ڪيترا سلسلا ڪم ڪري سگهن ٿا ان کي ڪنٽرول ڪرڻ جو آسان ترين طريقو هڪ سيمفور آهي. جيئن ريل گاڏي تي. سائي روشني تي آهي - توهان ڪري سگهو ٿا. ڳاڙهي روشني تي آهي - اسان انتظار ڪري رهيا آهيون. اسان هڪ سيمفور کان ڇا توقع ڪريون ٿا؟ اجازتون. اجازت انگريزيءَ ۾ - permit. اجازت حاصل ڪرڻ لاء، توهان کي ان کي حاصل ڪرڻو پوندو، جيڪو انگريزيء ۾ حاصل ڪيو ويندو. ۽ جڏهن اجازت جي ضرورت نه رهي ته اسان کي ان کي ڇڏڻو پوندو، يعني ان کي ڇڏايو يا ان کي ختم ڪري ڇڏيو، جنهن کي انگريزيءَ ۾ ڇڏڻو پوندو. اچو ته ڏسو ته اهو ڪيئن ڪم ڪري ٿو. اسان کي ڪلاس درآمد ڪرڻو پوندو 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. انگريزيءَ ۾ CountDown هڪ ڳڻپ آهي، ۽ Latch هڪ بولٽ يا latch آهي. اهو آهي، جيڪڏهن اسان ان کي ترجمو ڪريون ٿا، ته اهو هڪ ڳڻپ سان گڏ هڪ لچ آهي. هتي اسان کي ڪلاس جي مناسب درآمد جي ضرورت آهي 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- اهو آهي، انتظار ڪريو جيستائين انسداد قيمت صفر ٿي وڃي. اها دلچسپ ڳالهه آهي ته اهڙي ڪائونٽر ڊسپوزيبل آهي. جيئن ته JavaDoc ۾ چيو ويو آهي - "جڏهن موضوعن کي هن طريقي سان بار بار ڳڻڻ گهرجي، ان جي بدران هڪ CyclicBarrier استعمال ڪريو"، اهو آهي، جيڪڏهن توهان کي ٻيهر استعمال جي قابل ڳڻپ جي ضرورت آهي، توهان کي ٻيو اختيار استعمال ڪرڻ جي ضرورت آهي، جنهن کي سڏيو ويندو آهي CyclicBarrier.

سائيڪل بيئريئر

جيئن ته نالو مشورو ڏئي ٿو، CyclicBarrierاهو هڪ چڪر واري رڪاوٽ آهي. اسان کي ڪلاس درآمد ڪرڻو پوندو java.util.concurrent.CyclicBarrier. اچو ته هڪ مثال ڏسو:
public static void main(String[] args) throws InterruptedException {
	Runnable action = () -> System.out.println("На старт!");
	CyclicBarrier berrier = new CyclicBarrier(3, action);
	Runnable task = () -> {
		try {
			berrier.await();
			System.out.println("Finished");
		} catch (BrokenBarrierException | InterruptedException e) {
			e.printStackTrace();
		}
	};
	System.out.println("Limit: " + berrier.getParties());
	for (int i = 0; i < 3; i++) {
		new Thread(task).start();
	}
}
جئين توهان ڏسي سگهو ٿا، موضوع تي عمل ڪري رهيو آهي await، اهو آهي، انتظار. انهي حالت ۾، رڪاوٽ جي قيمت گھٽائي ٿي. رڪاوٽ کي ٽوٽل سمجهيو ويندو آهي ( berrier.isBroken()) جڏهن ڳڻپ صفر تائين پهچي ٿي. رڪاوٽ کي ريٽ ڪرڻ لاء، توهان کي ڪال ڪرڻ جي ضرورت آهي berrier.reset()، جيڪا غائب هئي CountDownLatch.

مٽائيندڙ

ايندڙ علاج آهي Exchanger. انگريزيءَ مان بدلي بدلي يا بدلي طور ترجمو ڪيو ويو آهي. A 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() + " обменялся с " + 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");
}
مثال ڏيکاري ٿو ته نئين ٿريڊ شروع ڪرڻ سان، هي ٿريڊ ويٽنگ موڊ ۾ ويندو، ڇاڪاڻ ته قطار خالي ٿي ويندي. ۽ پوءِ mainٿريڊ لکندو ”ميسيج“. ساڳئي وقت، اهو ضروري وقت تائين بند ٿي ويندو جيستائين اهو قطار مان هي متن عنصر حاصل ڪري. هن موضوع تي توهان پڻ پڙهي سگهو ٿا " SynchronousQueue Vs Exchanger ".

فيزر

۽ آخرڪار، سڀ کان مٺي شيء - Phaser. اسان کي ڪلاس درآمد ڪرڻو پوندو java.util.concurrent.Phaser. اچو ته هڪ سادي مثال ڏسو:
public static void main(String[] args) throws InterruptedException {
        Phaser phaser = new Phaser();
        // Вызывая метод register, мы регистрируем текущий поток (main) How участника
        phaser.register();
        System.out.println("Phasecount is " + phaser.getPhase());
        testPhaser(phaser);
        testPhaser(phaser);
        testPhaser(phaser);
        // Через 3 секунды прибываем к барьеру и снимаемся регистрацию. Кол-во прибывших = кол-во регистраций = пуск
        Thread.sleep(3000);
        phaser.arriveAndDeregister();
        System.out.println("Phasecount is " + phaser.getPhase());
    }

    private static void testPhaser(final Phaser phaser) {
        // Говорим, что будет +1 участник на Phaser
        phaser.register();
        // Запускаем новый поток
        new Thread(() -> {
            String name = Thread.currentThread().getName();
            System.out.println(name + " arrived");
            phaser.arriveAndAwaitAdvance(); //threads register arrival to the phaser.
            System.out.println(name + " after passing barrier");
        }).start();
    }
مثال ڏيکاري ٿو ته رڪاوٽ، جڏهن Phaser'a' استعمال ڪندي، ٽوڙي ويندي آهي جڏهن رجسٽريشن جو تعداد رڪاوٽ تي اچڻ وارن جي تعداد سان ٺهڪي اچي ٿو. Phaserتوھان ھب مان آرٽيڪل ۾ وڌيڪ ڳولي سگھو ٿا " نئون فيزر سنڪرونائزر ".

نتيجا

جئين توهان مثالن مان ڏسي سگهو ٿا، موضوعن کي هم وقت سازي ڪرڻ جا مختلف طريقا آهن. ان کان اڳ مون multithreading بابت ڪجهه ياد ڪرڻ جي ڪوشش ڪئي، اميد اٿم ته پوئين حصا ڪارآمد هئا. چون ٿا ته ملٽي ٿريڊنگ جو رستو شروع ٿئي ٿو ڪتاب ”جاوا اتفاق راءِ عملي ۾“. جيتوڻيڪ اهو 2006 ۾ ٻاهر آيو، ماڻهن جو جواب آهي ته ڪتاب ڪافي بنيادي آهي ۽ اڃا تائين هڪ پنچ پيڪ ڪري ٿو. مثال طور، توهان هتي بحث پڙهي سگهو ٿا: " ڇا Java Concurrency In Practice اڃا به صحيح آهي؟ " اهو پڻ مددگار آهي بحث مان لنڪ پڙهڻ لاء. مثال طور، ڪتاب جي هڪ لنڪ آهي " The Well-Grounded Java Developer "، جنهن ۾ اهو ڌيان ڏيڻ جي قابل آهي " باب 4. جديد اتفاق ". ساڳئي موضوع تي هڪ ٻيو سڄو جائزو آهي: " ڇا جاوا ڪرنسي عملي طور تي اڃا تائين جاوا 8 جي دور ۾ لاڳاپيل آهي ". انهي ۾ پڻ صلاحون آهن ته توهان کي ڇا پڙهڻ گهرجي واقعي موضوع کي سمجهڻ لاءِ. ان کان پوء، توهان هڪ ويجهڙائي سان ڏسي سگهو ٿا اهڙي شاندار ڪتاب تي " OCA OCP JavaSE 8 پروگرامر مشق ٽيسٽ ". اسان ٻئي حصي ۾ دلچسپي رکون ٿا، اهو آهي، او سي پي. ۽ "∫" ۾ ٽيسٽون آهن. هي ڪتاب وضاحتن سان گڏ سوال ۽ جواب ٻنهي تي مشتمل آهي. مثال طور: توھان جاوا کي ھڪڙي سلسلي سان خراب نٿا ڪري سگھو: حصو VI - رڪاوٽ ڏانھن!  - 3ڪيترائي چوڻ شروع ڪري سگھن ٿا ته اهو صرف طريقن جو هڪ ٻيو يادگار آهي. هڪ پاسي، ها. ٻئي طرف، هن سوال کي ياد ڪندي جواب ڏئي سگهجي ٿو ته ExecutorServiceهي هڪ قسم جو "اپ گريڊ" آهي Executor. ۽ Executorان جو مقصد صرف موضوعن جي ٺاھڻ جي طريقي کي لڪائڻ لاء آھي، پر انھن کي عمل ڪرڻ جو بنيادي طريقو نه آھي، اھو آھي، ھڪڙي نئين سلسلي ۾ ھلڻ Runnable. تنهن ڪري، execute(Callable)نه، ڇاڪاڻ ته انهن صرف طريقا شامل ڪيا ExecutorServiceجيڪي واپس ڪري سگهن ٿا . جئين توهان ڏسي سگهو ٿا، اسان طريقن جي هڪ فهرست کي ياد ڪري سگهون ٿا، پر اهو اندازو لڳائڻ تمام آسان آهي ته اسان پاڻ کي طبقن جي فطرت کي ڄاڻون ٿا. خير، موضوع تي ڪجهه اضافي مواد: ExecutorsubmitFuture #وياچسلاو
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION