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

توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو I - موضوع

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

تعارف

Multithreading جاوا ۾ ان جي شروعاتي ڏينهن کان تعمير ڪئي وئي آهي. تنهن ڪري اچو ته هڪ تڪڙو نظر وجهون ته ملٽي ٿريڊنگ ڇا آهي. توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو I - موضوع - 1اچو ته شروعاتي نقطي طور Oracle کان سرڪاري سبق وٺون: ” سبق: ”هيلو ورلڊ! ايپليڪيشن “. اچو ته اسان جي هيلو ورلڊ ايپليڪيشن جو ڪوڊ تبديل ڪريون ٿورڙو ھيٺ ڏنل:
class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello, " + args[0]);
    }
}
argsجڏهن پروگرام شروع ٿئي ٿو ته پاس ڪيل ان پٽ پيٽرولر جو هڪ صف آهي. اچو ته هن ڪوڊ کي فائل ۾ هڪ نالي سان محفوظ ڪريون جيڪو ڪلاس ۽ ايڪسٽينشن جي نالي سان ملي .java. اچو ته javac يوٽيلٽي کي استعمال ڪندي گڏ ڪريون : javac HelloWorldApp.java ان کان پوء، اسان جي ڪوڊ کي ڪجهه پيٽرولر سان ڪال ڪريو، مثال طور، راجر: java HelloWorldApp Roger توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو I - موضوع - 2اسان جي ڪوڊ ۾ هاڻي هڪ سنگين نقص آهي. جيڪڏهن اسان ڪنهن به دليل کي پاس نه ڪندا آهيون (يعني صرف java HelloWorldApp تي عمل ڪريو)، اسان کي هڪ غلطي ملندي:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
        at HelloWorldApp.main(HelloWorldApp.java:3)
نالي واري سلسلي ۾ هڪ استثنا (يعني هڪ غلطي) ٿي وئي آهي main. اهو ظاهر ٿئي ٿو ته جاوا ۾ ڪجهه قسم جا موضوع آهن؟ هتي اسان جو سفر شروع ٿئي ٿو.

جاوا ۽ سلسلا

سمجھڻ لاءِ ته ٿريڊ ڇا آھي، توھان کي سمجھڻ جي ضرورت آھي ته جاوا ايپليڪيشن ڪيئن شروع ٿئي ٿي. اچو ته اسان جو ڪوڊ هن ريت تبديل ڪريون:
class HelloWorldApp {
    public static void main(String[] args) {
		while (true) {
			//Do nothing
		}
	}
}
هاڻي اچو ته ان کي ٻيهر گڏ ڪريون javac استعمال ڪندي. اڳيون، سهولت لاءِ، اسان پنهنجي جاوا ڪوڊ کي الڳ ونڊو ۾ هلائينداسين. ونڊوز تي توهان هن طرح ڪري سگهو ٿا: start java HelloWorldApp. ھاڻي، jps يوٽيليٽي استعمال ڪندي ، اچو ته ڏسون ته جاوا اسان کي ڪھڙي معلومات ٻڌائيندو: توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو I - موضوع - 3پھريون نمبر آھي PID يا پروسيس ID، پروسيس جي سڃاڻپ ڪندڙ. هڪ عمل ڇا آهي؟
Процесс — это совокупность codeа и данных, разделяющих общее виртуальное addressное пространство.
پروسيس جي مدد سان، مختلف پروگرامن جي عمل کي هڪ ٻئي کان الڳ ڪيو ويو آهي: هر ايپليڪيشن ٻين پروگرامن سان مداخلت ڪرڻ کان سواء پنهنجي پنهنجي ياداشت واري علائقي کي استعمال ڪري ٿو. آئون توهان کي وڌيڪ تفصيل سان مضمون پڙهڻ جي صلاح ڏيان ٿو: " https://habr.com/post/164487/ ". هڪ عمل ٿريڊن کان سواءِ موجود نه ٿو رهي سگهي، تنهنڪري جيڪڏهن ڪو عمل موجود آهي ته ان ۾ گهٽ ۾ گهٽ هڪ ڌاڳو موجود آهي. اهو ڪيئن ٿئي ٿو جاوا ۾؟ جڏهن اسان هڪ جاوا پروگرام هلائيندا آهيون، ان جي عمل سان شروع ٿئي ٿي main. اسان پروگرام ۾ داخل ٿيڻ جو قسم آھيون، تنھنڪري ھن خاص طريقي کي mainانٽري پوائنٽ، يا ”انٽري پوائنٽ“ چئبو آھي. طريقو mainهميشه هجڻ گهرجي public static voidته جيئن جاوا ورچوئل مشين (JVM) اسان جي پروگرام تي عمل ڪرڻ شروع ڪري سگهي. ڏسو " جاوا مکيه طريقو جامد ڇو آهي؟ " وڌيڪ تفصيل لاءِ. اهو ظاهر ٿئي ٿو ته جاوا لانچر (java.exe يا javaw.exe) هڪ سادي ايپليڪيشن آهي (سادو سي ايپليڪيشن): اهو مختلف ڊي ايل ايل لوڊ ڪري ٿو، جيڪي اصل ۾ JVM آهن. جاوا لانچر Java Native Interface (JNI) ڪالن جو هڪ مخصوص سيٽ ٺاهي ٿو. JNI اهو ميکانيزم آهي جيڪو جاوا ورچوئل مشين جي دنيا ۽ C++ جي دنيا کي پل ڪري ٿو. اهو ظاهر ٿئي ٿو ته لانچر JVM نه آهي، پر ان جو لوڊ ڪندڙ. اهو ڄاڻي ٿو صحيح حڪمن تي عمل ڪرڻ لاءِ JVM شروع ڪرڻ لاءِ. ڄاڻي ٿو ته JNI ڪالون استعمال ڪندي سڀني ضروري ماحول کي ڪيئن منظم ڪجي. ماحول جي هن تنظيم ۾ هڪ مکيه موضوع جي تخليق پڻ شامل آهي، جنهن کي عام طور تي سڏيو ويندو آهي main. وڌيڪ واضع طور تي ڏسڻ لاءِ ته جاوا جي عمل ۾ ڪهڙيون سٽون رهن ٿيون، اسان استعمال ڪريون ٿا jvisualvm پروگرام ، جيڪو JDK ۾ شامل آهي. پروسيس جي پيڊ کي ڄاڻڻ سان، اسان ان تي فوري طور تي ڊيٽا کولي سگھون ٿا: jvisualvm --openpid айдипроцесса توھان جاوا کي ھڪڙي سلسلي سان برباد نٿا ڪري سگھو: حصو I - موضوع - 4دلچسپ ڳالهه اها آهي ته، هر سلسلي کي پروسيس لاء مختص ڪيل ميموري ۾ پنهنجو الڳ علائقو آهي. هن ياداشت جي جوڙجڪ کي اسٽيڪ سڏيو ويندو آهي. هڪ اسٽيڪ فريم تي مشتمل آهي. هڪ فريم هڪ طريقو سڏڻ جو نقطو آهي، عمل جي نقطي. ھڪڙي فريم کي StackTraceElement جي طور تي پڻ پيش ڪري سگھجي ٿو (ڏسو جاوا API لاء StackTraceElement ). توھان وڌيڪ پڙھي سگھوٿا ميموري بابت ھر سلسلي ۾ مختص ڪيل ھتي . جيڪڏهن اسان جاوا API تي نظر وجهون ٿا ۽ لفظ Thread جي ڳولا ڪنداسين، اسان ڏسنداسين ته اتي هڪ ڪلاس آهي java.lang.Thread . اھو اھو طبقو آھي جيڪو جاوا ۾ ھڪڙي وهڪرو جي نمائندگي ڪري ٿو، ۽ اھو اھو آھي جيڪو اسان کي ڪم ڪرڻو پوندو. Thread'ом Java не испортишь: Часть I — потоки - 5

java.lang.Thread

جاوا ۾ هڪ سلسلي کي ڪلاس جي مثال طور پيش ڪيو ويو آهي java.lang.Thread. اهو فوري طور تي سمجهڻ جي قابل آهي ته جاوا ۾ ٿريڊ ڪلاس جا مثال پاڻ ۾ موضوع نه آهن. هي صرف هڪ قسم جو API آهي هيٺين سطح جي موضوعن لاءِ جيڪي JVM ۽ آپريٽنگ سسٽم پاران منظم ڪيا ويندا آهن. جڏهن اسان جاوا لانچر استعمال ڪندي JVM لانچ ڪندا آهيون، اهو هڪ نالي سان هڪ مکيه ٿريڊ ٺاهي ٿو main۽ ڪيترائي وڌيڪ سروس ٿريڊس. جيئن ته ٿريڊ ڪلاس جي JavaDoc ۾ چيو ويو آهي: When a Java Virtual Machine starts up, there is usually a single non-daemon thread ٿريڊ جا 2 قسم آهن: ڊيمون ۽ غير ڊيمون. ڊيمون ٿريڊز پس منظر جا سلسلا (سروس ٿريڊس) آھن جيڪي پس منظر ۾ ڪجھ ڪم ڪن ٿا. هي دلچسپ اصطلاح ”Maxwell’s demon“ جو حوالو آهي، جنهن بابت توهان وڌيڪ پڙهي سگهو ٿا وڪيپيڊيا جي مضمون ۾ ” شيطانن “ بابت. جيئن ته دستاويز ۾ بيان ڪيو ويو آهي، JVM پروگرام (عمل) تي عمل جاري رکي ٿو جيستائين:
  • Runtime.exit طريقو نه سڏيو ويندو آهي
  • سڀئي غير ڊيمون موضوعن پنهنجو ڪم مڪمل ڪيو (ٻئي بغير غلطين ۽ استثنا سان اڇلائي)
انهيء ڪري اهم تفصيل: ڊيمن جي سلسلي کي ختم ڪري سگهجي ٿو ڪنهن به حڪم تي عمل ڪيو پيو وڃي. تنهن ڪري، انهن ۾ ڊيٽا جي سالميت جي ضمانت نه آهي. تنهن ڪري، ڊيمون موضوع ڪجهه خدمت جي ڪمن لاء مناسب آهن. مثال طور، جاوا ۾ ھڪڙو ٿريڊ آھي جيڪو گاربيج ڪليڪٽر (GC) سان لاڳاپيل حتمي طريقن يا موضوعن جي پروسيسنگ لاءِ ذميوار آھي. هر سلسلي جو تعلق ڪنهن نه ڪنهن گروهه سان آهي ( ThreadGroup ). ۽ گروهه هڪ ٻئي ۾ داخل ٿي سگهن ٿا، ڪجهه ترتيب يا جوڙجڪ ٺاهي.
public static void main(String []args){
	Thread currentThread = Thread.currentThread();
	ThreadGroup threadGroup = currentThread.getThreadGroup();
	System.out.println("Thread: " + currentThread.getName());
	System.out.println("Thread Group: " + threadGroup.getName());
	System.out.println("Parent Group: " + threadGroup.getParent().getName());
}
گروپ توهان کي وهڪري جي انتظام کي منظم ڪرڻ ۽ انهن جي ٽريڪ رکڻ جي اجازت ڏين ٿا. گروپن کان علاوه، موضوعن جو پنهنجو استثنا هينڊلر آهي. اچو ته هڪ مثال ڏسو:
public static void main(String []args) {
	Thread th = Thread.currentThread();
	th.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
		@Override
		public void uncaughtException(Thread t, Throwable e) {
			System.out.println("An error occurred: " + e.getMessage());
		}
	});
    System.out.println(2/0);
}
صفر طرفان ڊويزن هڪ غلطي جو سبب بڻجندو جيڪو سنڀاليندڙ طرفان پڪڙيو ويندو. جيڪڏهن توهان پاڻ هينڊلر جي وضاحت نه ڪندا آهيو، ڊفالٽ هينڊلر عمل درآمد ڪم ڪندو، جيڪو StdError ۾ غلطي جي اسٽيڪ ڏيکاريندو. توھان وڌيڪ پڙھي سگھوٿا جائزو ۾ http://pro-java.ru/java-dlya-opytnyx/obrabotchik-neperexvachennyx-isklyuchenij-java/ ". ان کان علاوه، موضوع کي ترجيح ڏني وئي آھي. توھان وڌيڪ پڙھي سگھو ٿا ترجيحن بابت. آرٽيڪل " ملٽي ٿريڊنگ ۾ جاوا موضوع جي ترجيح ".

تار ٺاهڻ

جيئن ته دستاويز ۾ بيان ڪيو ويو آهي، اسان وٽ 2 طريقا آهن هڪ موضوع ٺاهڻ لاء. پهرين توهان جو وارث پيدا ڪرڻ آهي. مثال طور:
public class HelloWorld{
    public static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("Hello, World!");
        }
    }

    public static void main(String []args){
        Thread thread = new MyThread();
        thread.start();
    }
}
جئين توهان ڏسي سگهو ٿا، ڪم طريقي سان شروع ڪيو ويو آهي run، ۽ ڌاڳو طريقي سان شروع ڪيو ويو آهي start. انهن کي پريشان نه ٿيڻ گهرجي، ڇاڪاڻ ته ... جيڪڏهن اسان اهو طريقو runسڌو هلون ٿا، ڪو نئون سلسلو شروع نه ٿيندو. اهو طريقو آهي startجيڪو JVM کان پڇي ٿو هڪ نئون موضوع ٺاهي. ٿريڊ مان اولاد وارو آپشن خراب آهي ڇو ته اسان ٿريڊ کي ڪلاس واري درجي ۾ شامل ڪريون ٿا. ٻيو نقصان اهو آهي ته اسان ”واحد ذميواري“ SOLID جي اصول جي ڀڃڪڙي ڪرڻ شروع ڪري رهيا آهيون، ڇاڪاڻ ته اسان جو طبقو هڪ ئي وقت ٿريڊ کي منظم ڪرڻ ۽ ڪجهه ڪم لاءِ ذميوار هوندو آهي جيڪو هن سلسلي ۾ انجام ڏنو وڃي. ڪهڙو صحيح آهي؟ جواب ان ئي طريقي ۾ آهي runجنهن کي اسين مٿي ڪريون ٿا:
public void run() {
	if (target != null) {
		target.run();
	}
}
ھتي targetڪجھ آھي java.lang.Runnable، جنھن کي اسين ڪلاس جو مثال ٺاھڻ وقت Thread ڏانھن منتقل ڪري سگھون ٿا. تنهن ڪري، اسان اهو ڪري سگهون ٿا:
public class HelloWorld{
    public static void main(String []args){
        Runnable task = new Runnable() {
            public void run() {
                System.out.println("Hello, World!");
            }
        };
        Thread thread = new Thread(task);
        thread.start();
    }
}
اهو پڻ Runnableجاوا 1.8 کان هڪ فنڪشنل انٽرفيس آهي. هي توهان کي اجازت ڏئي ٿو ٽاسڪ ڪوڊ لکڻ لاءِ ٿريڊن لاءِ اڃا به وڌيڪ خوبصورتي سان:
public static void main(String []args){
	Runnable task = () -> {
		System.out.println("Hello, World!");
	};
	Thread thread = new Thread(task);
	thread.start();
}

ڪُل

تنهن ڪري، مون کي اميد آهي ته هن ڪهاڻي مان اهو واضح ٿئي ٿو ته هڪ وهڪرو ڇا آهي، اهي ڪيئن موجود آهن ۽ انهن سان ڪهڙو بنيادي آپريشن ڪري سگهجي ٿو. ايندڙ حصي ۾ ، اهو سمجهڻ جي قابل آهي ته موضوع ڪيئن هڪ ٻئي سان لهه وچڙ ۾ آهن ۽ انهن جي زندگي جي چڪر ڇا آهي. #وياچسلاو
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION