Java-da multithreading həll etdiyi problemlər
Əslində, Java multithreading iki əsas problemi həll etmək üçün icad edilmişdir:-
Eyni anda bir neçə hərəkəti yerinə yetirin.
Yuxarıdakı nümunədə müxtəlif iplər (yəni ailə üzvləri) paralel olaraq bir neçə hərəkət etdi: qabları yudu, mağazaya getdi, əşyaları qatladı.
Daha çox “proqramçı” nümunəsi verilə bilər. Təsəvvür edin ki, istifadəçi interfeysi olan bir proqramınız var. Davam et düyməsini sıxdıqda proqram daxilində bəzi hesablamalar baş verməli və istifadəçi aşağıdakı interfeys ekranını görməlidir. Bu hərəkətlər ardıcıl olaraq həyata keçirilirsə, "Davam et" düyməsini basdıqdan sonra proqram sadəcə dondurulacaq. İstifadəçi bütün daxili hesablamalar tamamlanana və proqram interfeysin çəkilməyə başlayacağı hissəyə çatana qədər “Davam et” düyməsi ilə eyni ekranı görəcək.
Yaxşı, bir neçə dəqiqə gözləyək!
Biz həmçinin proqramımızı yenidən düzəldə və ya proqramçıların dediyi kimi “paralelləşdirə” bilərik. Lazımi hesablamalar bir ipdə aparılsın, digərində isə interfeys göstərilsin. Əksər kompüterlərdə bunun üçün kifayət qədər resurs var. Bu vəziyyətdə, proqram "axmaq" olmayacaq və istifadəçi içəridə baş verənlərdən narahat olmadan interfeys ekranları arasında sakitcə hərəkət edəcək. qarışmır :)
-
Hesablamaları sürətləndirin.
Burada hər şey daha sadədir. Əgər prosessorumuz bir neçə nüvəyə malikdirsə və əksər prosessorlar indi çoxnüvəlidirsə, tapşırıqlarımızın siyahısı bir neçə nüvə ilə paralel olaraq həll edilə bilər. Aydındır ki, əgər bizə 1000 problemi həll etmək lazımdırsa və onların hər biri bir saniyədə həll edilərsə, bir nüvə 1000 saniyəyə, iki nüvə 500 saniyəyə, üç nüvə 333 saniyədən bir az çox müddətdə siyahının öhdəsindən gələcək və s.
Thread
. Yəni 10 mövzu yaratmaq və işlətmək üçün bu sinifin 10 obyektinə ehtiyacınız olacaq. Ən sadə nümunəni yazaq:
public class MyFirstThread extends Thread {
@Override
public void run() {
System.out.println("I'm Thread! My name is " + getName());
}
}
Mövzular yaratmaq və işə salmaq üçün bir sinif yaratmalı və onu java.lang
. Thread
və içindəki metodu ləğv edin run()
. Sonuncu çox vacibdir. Məhz metodda run()
ipimizin icra etməli olduğu məntiqi təyin edirik. İndi bir nümunə yaradıb MyFirstThread
onu işə salsaq, üsul run()
konsolda öz adı ilə bir sətir çap edəcək: metod getName()
avtomatik olaraq təyin olunan ipin “sistem” adını çap edir. Baxmayaraq ki, əslində niyə “əgər”? Yaradaq və sınaqdan keçirək!
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.start();
}
}
}
Konsol çıxışı: I'm Thread! Mənim adım Thread-2 I'm Thread! Mənim adım Thread-1 I'm Thread! Mənim adım Thread-0 I'm Thread! Mənim adım Thread-3 I'm Thread! Mənim adım Thread-6 I'm Thread! Mənim adım Thread-7 I'm Thread! Mənim adım Thread-4 I'm Thread! Mənim adım Thread-5 I'm Thread! Mənim adım Thread-9 I'm Thread! Mənim adım Thread-8MyFirstThread
Biz miras qalan 10 mövzu (obyekt) yaradırıq Thread
və obyektin metodunu çağıraraq onları işə salırıq start()
. Metod çağırıldıqdan sonra start()
onun metodu işə başlayır run()
və orada yazılmış məntiq icra olunur. Diqqət edin: mövzu adları qaydasında deyil. Olduqca qəribədir, niyə onlar növbə ilə edam olunmayıb: Thread-0
, Thread-1
, Thread-2
və s. Bu, standart, “ardıcıl” düşüncənin işləməyəcəyinə tam bir nümunədir. Fakt budur ki, bu halda biz yalnız 10 mövzu yaratmaq və işə salmaq üçün əmrlər veririk. Onların hansı ardıcıllıqla işə salınması mövzu planlayıcısı tərəfindən müəyyən edilir: əməliyyat sisteminin daxilində xüsusi mexanizm. Onun necə strukturlaşdırıldığı və hansı prinsip əsasında qərarlar qəbul etdiyi çox mürəkkəb bir mövzudur və biz indi buna dalmayacağıq. Xatırlamaq lazım olan əsas şey proqramçının mövzunun icrası ardıcıllığına nəzarət edə bilməməsidir. Vəziyyətin ciddiliyini dərk etmək üçün main()
yuxarıdakı nümunədəki metodu bir neçə dəfə daha işlətməyə çalışın. İkinci konsol çıxışı: I'm Thread! Mənim adım Thread-0 I'm Thread! Mənim adım Thread-4 I'm Thread! Mənim adım Thread-3 I'm Thread! Mənim adım Thread-2 I'm Thread! Mənim adım Thread-1 I'm Thread! Mənim adım Thread-5 I'm Thread! Mənim adım Thread-6 I'm Thread! Mənim adım Thread-8 I'm Thread! Mənim adım Thread-9 I'm Thread! Mənim adım Thread-7 Üçüncü konsol çıxışı: I'm Thread! Mənim adım Thread-0 I'm Thread! Mənim adım Thread-3 I'm Thread! Mənim adım Thread-1 I'm Thread! Mənim adım Thread-2 I'm Thread! Mənim adım Thread-6 I'm Thread! Mənim adım Thread-4 I'm Thread! Mənim adım Thread-9 I'm Thread! Mənim adım Thread-5 I'm Thread! Mənim adım Thread-7 I'm Thread! Mənim adım Thread-8-dir
Çox iş parçacığının yaratdığı problemlər
Kitablarla nümunədə siz çoxilliklərin kifayət qədər vacib problemləri həll etdiyini və onun istifadəsi proqramlarımızın işini sürətləndirdiyini gördünüz. Çox hallarda - dəfələrlə. Ancaq çox iş parçacığının mürəkkəb bir mövzu hesab edilməsi boş yerə deyil. Axı, düzgün istifadə edilmədikdə, onları həll etmək əvəzinə problemlər yaradır. “Problem yaradın” deyəndə mücərrəd bir şeyi nəzərdə tutmuram. Multithreading səbəb ola biləcəyi iki xüsusi problem var: çıxılmaz vəziyyət və yarış vəziyyəti. Deadlock elə bir vəziyyətdir ki, çoxlu mövzular bir-birinin tutduğu resursları gözləyir və onlardan heç biri icra etməyə davam edə bilmir. Gələcək mühazirələrdə bu barədə daha çox danışacağıq, lakin hələlik bu nümunə kifayət edəcək: Təsəvvür edin ki, thread-1 hansısa Obyekt-1 ilə, ip-2 isə Obyekt-2 ilə işləyir. Proqram belə yazılmışdır:- Thread-1 Obyekt-1 ilə işləməyi dayandıracaq və Thread-2 Obyekt 2 ilə işləməyi dayandırıb Obyekt-1-ə keçən kimi Obyekt-2-yə keçəcək.
- Thread-1 Obyekt 1 ilə işləməyi dayandırıb Obyekt-2-yə keçən kimi Thread-2 Obyekt-2 ilə işləməyi dayandıracaq və Obyekt-1-ə keçəcək.
public class MyFirstThread extends Thread {
@Override
public void run() {
System.out.println("Выполнен поток " + getName());
}
}
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.start();
}
}
}
İndi təsəvvür edin ki, proqram yemək hazırlayan robotun işinə cavabdehdir! Thread-0 yumurtaları soyuducudan çıxarır. Axın 1 sobanı yandırır. Stream-2 qovurma qabını çıxarıb ocağın üstünə qoyur. Axın 3 sobada od yandırır. Stream 4 tavaya yağ tökün. Stream 5 yumurtaları qırır və tavaya tökür. Stream 6 qabıqları zibil qutusuna atır. Stream-7 hazır omletləri istidən çıxarır. Potok-8 boşqaba omlet qoyur. Stream-9 qabları yuyur. Proqramımızın nəticələrinə baxın: Mövzu-0 yerinə yetirildi Mövzu-2 mövzu icra edildi Mövzu-1 mövzu icra edildi Mövzu-4 mövzu yerinə yetirildi Mövzu-9 mövzu icra edildi Mövzu-5 mövzu icra edildi Mövzu-8 mövzu icra edildi Mövzu-7 mövzu icra edildi Mövzu-7 mövzu icra edildi -3 Mövzu-6 mövzu icra edildi. Skript əyləncəlidir? :) Və hamısı ona görə ki, proqramımızın işləməsi iplərin icra olunma ardıcıllığından asılıdır. Ardıcıllığın ən kiçik pozuntusunda mətbəximiz cəhənnəmə çevrilir və ağlını itirmiş robot ətrafdakı hər şeyi məhv edir. Bu, həm də bir neçə dəfə eşidəcəyiniz çoxillik proqramlaşdırmada ümumi problemdir. Mühazirənin sonunda mən sizə multithreading haqqında kitab tövsiyə etmək istərdim.
GO TO FULL VERSION