JavaRush /Java Blogu /Random-AZ /Mövzu ilə Java-nı korlaya bilməzsiniz: I hissə - Mövzular...
Viacheslav
Səviyyə

Mövzu ilə Java-nı korlaya bilməzsiniz: I hissə - Mövzular

Qrupda dərc edilmişdir

Giriş

Multithreading Java-da ilk günlərdən bəri qurulmuşdur. Beləliklə, gəlin multithreading nə ilə əlaqəli olduğuna qısaca nəzər salaq. Siz Java-nı Mövzu ilə məhv edə bilməzsiniz: I Hissə - Mövzular - 1Başlanğıc nöqtəsi olaraq Oracle-dan rəsmi dərsi götürək: " Dərs: "Salam Dünya!" Tətbiqi ". Hello World tətbiqimizin kodunu bir az aşağıdakılara dəyişək:
class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello, " + args[0]);
    }
}
argsproqram başlayanda ötürülən giriş parametrləri massividir. Gəlin bu kodu sinfin adına və genişlənməsinə uyğun gələn adla faylda saxlayaq .java. Gəlin javac yardım proqramından istifadə edərək kompilyasiya edək : javac HelloWorldApp.java Bundan sonra kodumuza hansısa parametrlə zəng edin, məsələn, Roger: java HelloWorldApp Roger Siz Java-nı Mövzu ilə məhv edə bilməzsiniz: I Hissə - Mövzular - 2İndi kodumuzda ciddi bir qüsur var. Heç bir arqumenti qəbul etməsək (yəni, sadəcə java HelloWorldApp-ı yerinə yetirsək), xəta alacağıq:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
        at HelloWorldApp.main(HelloWorldApp.java:3)
adlı mövzuda istisna (yəni xəta) baş verdi main. Belə çıxır ki, Java-da bir növ mövzu var? Səyahətimiz buradan başlayır.

Java və mövzular

Bir mövzunun nə olduğunu başa düşmək üçün Java proqramının necə işə salındığını başa düşməlisiniz. Kodumuzu aşağıdakı kimi dəyişdirək:
class HelloWorldApp {
    public static void main(String[] args) {
		while (true) {
			//Do nothing
		}
	}
}
İndi javac istifadə edərək onu yenidən kompilyasiya edək. Sonra, rahatlıq üçün Java kodumuzu ayrıca pəncərədə işlədəcəyik. Windows-da bunu belə edə bilərsiniz: start java HelloWorldApp. İndi jps yardım proqramından istifadə edərək Java-nın bizə hansı məlumatı deyəcəyini görək: Siz Java-nı Mövzu ilə məhv edə bilməzsiniz: I Hissə - Mövzular - 3Birinci nömrə PID və ya Proses ID-sidir, proses identifikatorudur. Proses nədir?
Процесс — это совокупность codeа и данных, разделяющих общее виртуальное addressное пространство.
Proseslərin köməyi ilə müxtəlif proqramların icrası bir-birindən təcrid olunur: hər bir proqram digər proqramlara müdaxilə etmədən öz yaddaş sahəsindən istifadə edir. Məqaləni daha ətraflı oxumağı məsləhət görürəm: " https://habr.com/post/164487/ ". Proses iplərsiz mövcud ola bilməz, ona görə də proses varsa, onda ən azı bir iplik mövcuddur. Java-da bu necə baş verir? Java proqramını işə saldığımız zaman onun icrası main. Biz bir növ proqrama daxil oluruq, ona görə də bu xüsusi metoda maingiriş nöqtəsi və ya “giriş nöqtəsi” deyilir. Metod mainhəmişə elə olmalıdır public static voidki, Java Virtual Maşın (JVM) proqramımızı icra etməyə başlaya bilsin. Ətraflı məlumat üçün " Java əsas metodu niyə statikdir? "-a baxın. Məlum oldu ki, java başlatma qurğusu (java.exe və ya javaw.exe) sadə proqramdır (sadə C proqramı): o, əslində JVM olan müxtəlif DLL-ləri yükləyir. Java başlatma proqramı xüsusi Java Native Interface (JNI) zəngləri dəsti edir. JNI Java Virtual Machine dünyası ilə C++ dünyası arasında körpü yaradan mexanizmdir. Məlum oldu ki, başlatma cihazı JVM deyil, onun yükləyicisidir. JVM-i işə salmaq üçün düzgün əmrləri bilir. JNI zənglərindən istifadə edərək bütün lazımi mühiti necə təşkil etməyi bilir. Ətraf mühitin bu təşkili adətən adlanan əsas ipin yaradılmasını da əhatə edir main. Java prosesində hansı mövzuların yaşadığını daha aydın görmək üçün JDK-ya daxil olan jvisualvm proqramından istifadə edirik. Prosesin pidini bilməklə, biz onun haqqında məlumatları dərhal aça bilərik: jvisualvm --openpid айдипроцесса Siz Java-nı Mövzu ilə məhv edə bilməzsiniz: I hissə - Mövzular - 4Maraqlıdır ki, hər bir ipin proses üçün ayrılmış yaddaşda öz ayrıca sahəsi var. Bu yaddaş strukturu stack adlanır. Yığın çərçivələrdən ibarətdir. Çərçivə metodu çağırma nöqtəsi, icra nöqtəsidir. Çərçivə StackTraceElement kimi də təmsil oluna bilər (bax: StackTraceElement üçün Java API ). Burada hər mövzuya ayrılmış yaddaş haqqında daha çox oxuya bilərsiniz . Java API- yə baxsaq və Thread sözünü axtarsaq, görərik ki, java.lang.Thread sinfi var . Java-da axını təmsil edən bu sinifdir və biz bununla işləməliyik. Siz Java-nı Mövzu ilə məhv edə bilməzsiniz: I Hissə - Mövzular - 5

java.lang.Mövzu

Java-da mövzu sinifin bir nümunəsi kimi təmsil olunur java.lang.Thread. Java-dakı Thread sinifinin nümunələrinin özləri mövzu olmadığını dərhal başa düşməyə dəyər. Bu, JVM və əməliyyat sistemi tərəfindən idarə olunan aşağı səviyyəli mövzular üçün sadəcə bir növ API-dir. Biz Java başlatma qurğusundan istifadə edərək JVM-i işə saldığımız zaman o, adı mainvə daha bir neçə xidmət ipi olan əsas ip yaradır. Thread sinfinin JavaDoc-da qeyd edildiyi kimi: When a Java Virtual Machine starts up, there is usually a single non-daemon thread 2 növ mövzu var: demonlar və qeyri-daemonlar. Daemon mövzuları arxa planda bəzi işləri yerinə yetirən arxa plan mövzularıdır (xidmət mövzuları). Bu maraqlı termin “Maksvellin iblisi”nə istinaddır, bu barədə daha çox “ cinlər ” haqqında Vikipediya məqaləsində oxuya bilərsiniz. Sənədlərdə qeyd edildiyi kimi, JVM proqramı (prosesi) yerinə yetirməyə davam edir:
  • Runtime.exit metodu çağırılmır
  • Bütün qeyri-daemon mövzuları işlərini tamamladı (həm səhvsiz, həm də atılan istisnalarla)
Beləliklə, vacib detal: demon ipləri yerinə yetirilən istənilən əmrdə dayandırıla bilər. Buna görə də, onlarda məlumatların bütövlüyü təmin edilmir. Buna görə də, demon ipləri bəzi xidmət tapşırıqları üçün uyğundur. Məsələn, Java-da Zibil Kollektoru (GC) ilə əlaqəli son üsulların və ya mövzuların işlənməsi üçün cavabdeh olan bir ip var. Hər mövzu hansısa qrupa ( ThreadGroup ) aiddir . Və qruplar bəzi iyerarxiya və ya struktur yaradaraq bir-birinə daxil ola bilər.
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());
}
Qruplar axınların idarə edilməsini sadələşdirməyə və onları izləməyə imkan verir. Qruplara əlavə olaraq mövzuların öz istisna işləyicisi var. Bir misala baxaq:
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);
}
Sıfıra bölmə işləyici tərəfindən tutulacaq bir xətaya səbəb olacaq. İşləyicini özünüz təyin etməsəniz, defolt işləyici tətbiqi işləyəcək və bu, StdError-da xəta yığınını göstərəcək. Daha ətraflı http://pro-java.ru/java-dlya-opytnyx/obrabotchik-neperexvachennyx-isklyuchenij-java/ "" icmalında oxuya bilərsiniz . Bundan əlavə, mövzunun prioriteti var. Prioritetlər haqqında ətraflı oxuya bilərsiniz. məqalə " Multithreading Java Thread Priority ".

Bir ipin yaradılması

Sənədlərdə deyildiyi kimi, ip yaratmaq üçün 2 yolumuz var. Birincisi, varisini yaratmaqdır. Misal üçün:
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();
    }
}
Gördüyünüz kimi, tapşırıq metodda run, iplik isə metodda işə salınır start. Onları çaşdırmamaq lazımdır, çünki... metodu birbaşa işə salsaq run, heç bir yeni başlıq açılmayacaq. startJVM-dən yeni mövzu yaratmağı xahiş edən üsuldur . Thread-dan nəsli olan seçim pisdir, çünki biz Thread-ı sinif iyerarxiyasına daxil edirik. İkinci çatışmazlıq ondan ibarətdir ki, biz “Tək Məsuliyyət” SOLID prinsipini pozmağa başlayırıq, çünki sinifimiz eyni vaxtda həm mövzunun idarə edilməsinə, həm də bu mövzuda yerinə yetirilməli olan bəzi tapşırıqlara cavabdeh olur. Hansı düzgündür? runCavab, ləğv etdiyimiz üsuldadır :
public void run() {
	if (target != null) {
		target.run();
	}
}
Sinif nümunəsini yaradan zaman Thread-a keçə biləcəyimiz targetbəziləri . java.lang.RunnableBuna görə də bunu edə bilərik:
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();
    }
}
O , həmçinin RunnableJava 1.8-dən bəri funksional interfeysdir. Bu, mövzular üçün tapşırıq kodunu daha da gözəl yazmağa imkan verir:
public static void main(String []args){
	Runnable task = () -> {
		System.out.println("Hello, World!");
	};
	Thread thread = new Thread(task);
	thread.start();
}

Ümumi

Beləliklə, ümid edirəm ki, bu hekayədən axın nədir, necə mövcuddur və onlarla hansı əsas əməliyyatları yerinə yetirmək olar. Növbəti hissədə iplərin bir-biri ilə necə qarşılıqlı əlaqədə olduğunu və onların həyat dövrünün nə olduğunu başa düşməyə dəyər. #Viaçeslav
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION