JavaRush /Java blogi /Random-UZ /Siz Java-ni mavzu bilan buzolmaysiz: I qism - mavzular
Viacheslav
Daraja

Siz Java-ni mavzu bilan buzolmaysiz: I qism - mavzular

Guruhda nashr etilgan

Kirish

Multithreading Java tilining dastlabki kunlaridan boshlab o'rnatilgan. Shunday qilib, keling, multithreading nima haqida ekanligini tezda ko'rib chiqaylik. Siz Java-ni mavzu bilan buzolmaydi: I qism - Mavzular - 1Keling, Oracle-dan rasmiy darsni boshlaylik: " Dars: "Salom dunyo!" Ilovasi ". Keling, Hello World ilovamiz kodini biroz o'zgartiraylik:
class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello, " + args[0]);
    }
}
args- bu dastur ishga tushganda uzatiladigan kirish parametrlari massivi. Keling, ushbu kodni sinf nomi va kengaytmasiga mos keladigan nomga ega faylga saqlaymiz .java. Keling, javac yordam dasturidan foydalanib kompilyatsiya qilaylik : javac HelloWorldApp.java Shundan so'ng, kodimizni qandaydir parametr bilan chaqiring, masalan, Rojer: java HelloWorldApp Roger Siz Java-ni mavzu bilan buzolmaysiz: I qism - Mavzular - 2Bizning kodimizda hozir jiddiy kamchilik bor. Agar biz hech qanday argumentni o'tkazib yubormasak (ya'ni java HelloWorldApp dasturini ishga tushirsak), biz xatoga duch kelamiz:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
        at HelloWorldApp.main(HelloWorldApp.java:3)
nomli mavzuda istisno (ya'ni xatolik) yuz berdi main. Ko'rinib turibdiki, Java-da qandaydir mavzular mavjud? Bu bizning sayohatimiz boshlanadi.

Java va mavzular

Tarmoq nima ekanligini tushunish uchun Java ilovasi qanday ishga tushirilishini tushunishingiz kerak. Keling, kodimizni quyidagicha o'zgartiramiz:
class HelloWorldApp {
    public static void main(String[] args) {
		while (true) {
			//Do nothing
		}
	}
}
Endi uni javac yordamida yana kompilyatsiya qilamiz. Keyinchalik, qulaylik uchun biz Java kodimizni alohida oynada ishga tushiramiz. Windows-da buni shunday qilishingiz mumkin: start java HelloWorldApp. Endi, jps yordam dasturidan foydalanib , Java bizga qanday ma'lumot berishini ko'rib chiqamiz: Siz Java-ni mavzu bilan buzolmaysiz: I qism - Mavzular - 3Birinchi raqam PID yoki Process ID, jarayon identifikatoridir. Jarayon nima?
Процесс — это совокупность codeа и данных, разделяющих общее виртуальное addressное пространство.
Jarayonlar yordamida turli dasturlarning bajarilishi bir-biridan ajratilgan: har bir dastur boshqa dasturlarga aralashmasdan o'z xotira maydonidan foydalanadi. Men sizga maqolani batafsil o'qishni maslahat beraman: " https://habr.com/post/164487/ ". Jarayon iplarsiz mavjud bo'lolmaydi, shuning uchun agar jarayon mavjud bo'lsa, unda kamida bitta ip mavjud. Bu Java'da qanday sodir bo'ladi? Java dasturini ishga tushirganimizda uning bajarilishi main. Biz qandaydir dasturga kiramiz, shuning uchun bu maxsus usul mainkirish nuqtasi yoki "kirish nuqtasi" deb ataladi. Usul mainhar doim shunday bo'lishi kerakki public static void, Java virtual mashinasi (JVM) bizning dasturimizni bajarishni boshlaydi. Batafsil ma'lumot uchun " Java asosiy usuli nima uchun statik? " bo'limiga qarang . Ma'lum bo'lishicha, java ishga tushirgich (java.exe yoki javaw.exe) oddiy dastur (oddiy C ilovasi): u turli xil DLL-larni yuklaydi, ular aslida JVM. Java ishga tushirgichi Java Native Interface (JNI) qo'ng'iroqlarining muayyan to'plamini amalga oshiradi. JNI Java virtual mashinasi dunyosi va C++ dunyosini bog'laydigan mexanizmdir. Ma'lum bo'lishicha, ishga tushirgich JVM emas, balki uning yuklovchisi. JVM ni ishga tushirish uchun bajarilishi kerak bo'lgan to'g'ri buyruqlarni biladi. JNI qo'ng'iroqlari yordamida barcha kerakli muhitni qanday tashkil qilishni biladi. Atrof-muhitning bunday tashkil etilishi, shuningdek, odatda deyiladi asosiy ipni yaratishni o'z ichiga oladi main. Java jarayonida qanday iplar yashashini aniqroq ko'rish uchun biz JDK tarkibiga kiritilgan jvisualvm dasturidan foydalanamiz. Jarayonning pidini bilib, biz u haqida ma'lumotni darhol ochishimiz mumkin: jvisualvm --openpid айдипроцесса Siz Java-ni mavzu bilan buzolmaysiz: I qism - Mavzular - 4Qizig'i shundaki, har bir ipning jarayon uchun ajratilgan xotirada o'ziga xos alohida maydoni mavjud. Ushbu xotira strukturasi stek deb ataladi. Stack ramkalardan iborat. Ramka - bu usulni chaqirish nuqtasi, bajarilish nuqtasi. Ram StackTraceElement sifatida ham taqdim etilishi mumkin ( StackTraceElement uchun Java API ga qarang ). Bu yerda har bir mavzu uchun ajratilgan xotira haqida ko'proq o'qishingiz mumkin . Agar Java API ni ko'rib chiqsak va Thread so'zini qidirsak java.lang.Thread klassi mavjudligini ko'ramiz . Aynan shu sinf Java-dagi oqimni ifodalaydi va biz shu bilan ishlashimiz kerak. Thread'ом Java не испортишь: Часть I — потоки - 5

java.lang.Thread

Java'dagi ip sinfning namunasi sifatida taqdim etiladi java.lang.Thread. Java'dagi Thread klassi misollarining o'zlari mavzular emasligini darhol tushunish kerak. Bu JVM va operatsion tizim tomonidan boshqariladigan past darajadagi oqimlar uchun faqat bir turdagi API. JVM ni java ishga tushirgich yordamida ishga tushirganimizda, u nomli mainva yana bir nechta xizmat ko'rsatish oqimlari bilan asosiy ish zarrachasini yaratadi. Thread sinfining JavaDoc dasturida aytilganidek: When a Java Virtual Machine starts up, there is usually a single non-daemon thread 2 turdagi mavzular mavjud: demonlar va demonlar bo'lmagan. Daemon iplari - bu fonda ba'zi ishlarni bajaradigan fon oqimlari (xizmat mavzulari). Bu qiziqarli atama "Maksvellning jinlari" ga ishora bo'lib, siz " jinlar " haqidagi Vikipediya maqolasida ko'proq o'qishingiz mumkin . Hujjatlarda ko'rsatilganidek, JVM dasturni (jarayonni) bajarishda davom etadi:
  • Runtime.exit usuli chaqirilmaydi
  • Demon bo'lmagan barcha iplar o'z ishlarini yakunladilar (ham xatosiz, ham istisnolarsiz)
Shuning uchun muhim tafsilot: demon iplari bajarilayotgan har qanday buyruqda tugatilishi mumkin. Shuning uchun ulardagi ma'lumotlarning yaxlitligi kafolatlanmaydi. Shuning uchun, demon iplari ba'zi xizmat vazifalari uchun mos keladi. Masalan, Java-da axlat yig'uvchi (GC) bilan bog'liq yakuniy usullar yoki mavzularni qayta ishlash uchun mas'ul bo'lgan ip mavjud. Har bir mavzu ma'lum bir guruhga tegishli ( ThreadGroup ). Guruhlar esa bir-biriga kirib, qandaydir ierarxiya yoki tuzilma hosil qilishi mumkin.
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());
}
Guruhlar oqimlarni boshqarishni soddalashtirish va ularni kuzatib borish imkonini beradi. Guruhlarga qo'shimcha ravishda, mavzular o'zlarining istisno ishlovchilariga ega. Keling, bir misolni ko'rib chiqaylik:
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);
}
Nolga bo'linish ishlov beruvchi tomonidan ushlanib qoladigan xatoga olib keladi. Agar siz ishlov beruvchini o'zingiz belgilamasangiz, standart ishlov beruvchini amalga oshirish ishlaydi, bu StdError-da xatolik to'plamini ko'rsatadi. Siz http://pro-java.ru/java-dlya-opytnyx/obrabotchik-neperexvachennyx-isklyuchenij-java/ " ko'rib chiqishda ko'proq o'qishingiz mumkin . Bundan tashqari, mavzu ustuvor ahamiyatga ega. Siz ustuvorliklar haqida ko'proq o'qishingiz mumkin. Maqola " Ko'p ish zarrachalarida Java Thread ustuvorligi ".

Tarmoq yaratish

Hujjatlarda aytilganidek, bizda ipni yaratishning 2 usuli mavjud. Birinchisi, merosxo'ringizni yaratishdir. Masalan:
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();
    }
}
Ko'rib turganingizdek, vazifa usulda run, ip esa usulda ishga tushiriladi start. Ularni chalkashtirib yubormaslik kerak, chunki... agar biz to'g'ridan-to'g'ri usulni ishga tushirsak run, yangi mavzu boshlanmaydi. Bu startJVM dan yangi ish zarrachasini yaratishni talab qiladigan usul. Thread avlodiga ega variant yomon, chunki biz Threadni sinf ierarxiyasiga kiritamiz. Ikkinchi kamchilik shundaki, biz "Yagona javobgarlik" SOLID tamoyilini buzishni boshlaymiz, chunki Bizning sinfimiz bir vaqtning o'zida ipni boshqarish uchun ham, ushbu mavzuda bajarilishi kerak bo'lgan ba'zi vazifalar uchun ham javobgar bo'ladi. Qaysi biri to'g'ri? runJavob biz bekor qiladigan usulda :
public void run() {
	if (target != null) {
		target.run();
	}
}
Mana , sinfning namunasini yaratishda Thread-ga o'tkazishimiz mumkin bo'lgan targetba'zilari . java.lang.RunnableShuning uchun biz buni qila olamiz:
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();
    }
}
Bu , shuningdek Runnable, Java 1.8 dan beri funktsional interfeysdir. Bu sizga mavzular uchun vazifa kodini yanada chiroyli yozish imkonini beradi:
public static void main(String []args){
	Runnable task = () -> {
		System.out.println("Hello, World!");
	};
	Thread thread = new Thread(task);
	thread.start();
}

Jami

Shunday qilib, umid qilamanki, bu hikoyadan oqim nima ekanligi, ular qanday mavjudligi va ular bilan qanday asosiy operatsiyalarni bajarish mumkinligi aniq bo'ladi. Keyingi qismda iplar bir-biri bilan qanday o'zaro ta'sir qilishini va ularning hayot aylanishi nima ekanligini tushunishga arziydi. #Viacheslav
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION