Java.util.concurrent paketi, müxtəlif siniflər təmin edən müxtəlif Java paralel proqramlarını ehtiva edir çox oxlu. Bu paket Java 5-dən başlayaraq təqdim olunur. Bundan əvvəl, istifadəçi paralel tətbiqetmələrin inkişafı üçün öz köməkçi proqramlarını yaratmalıdır.
Bu təlimdə bütün Java paralel proqramlarına ümumi baxışı görəcəyik.
Mündəricat
Java Paralel Utilities
Java.util.concurrent paketi, paralelliyi və ya çox işlənməyi həyata keçirmək üçün istifadə edə biləcəyimiz aşağıdakı sinifləri ehtiva edir.
İcraçı xidmət
The İcraçı xidmət asinxron tapşırıq icrasını həyata keçirən java.util.concurrent paketinin bir hissəsi olan bir interfeysdir. Bu Java paralel proqramı, tapşırığın icrasını eyni zamanda arxa planda yerinə yetirir. Bir İcraçı Xidmət yaratarkən, a yarada bilərik iplik hovuzu newFixedThreadPool (int size) metodundan istifadə edərək lazımi ölçüdə. Metodu istifadə edərək tək bir mövzu da yarada bilərik newSingleThreadExecutor(ThreadFactory threadFactory).
Başqa bir yol newScheduledThreadPool(int size)
.
ExecutorService exec = Executors.newFixedThreadPool(5); ExecutorService exec = Executors.newSingleThreadExecutor(); ExecutorService exec = Executors.newScheduledThreadPool(5);
İcra üçün İcraçı Xidmətə tapşırıq verə biləcəyimiz bir çox yol var.
- icra (Runnable)
- təqdim et (Runnable)
- təqdim et (Çağırılan)
- invokeAny ()
- invokeAll ()
İcra başa çatdıqdan sonra aşağıda göstərilən metodlardan hər hansı birini istifadə edərək İcraçı Xidməti bağlamaq çox vacibdir.
- söndür()
- shutdownNow ()
- awaitTermination ()
Planlaşdırılmış İcraçı Xidmət
Bu da birdir ExecutorService
tapşırığı planlı bir vaxt aralığından sonra və ya müəyyən bir gecikmədən sonra yerinə yetirir. İstifadə edərək yaratmaq istədiyimiz mövzu sayını təyin edə bilərik newScheduledThreadPool
. Cədvəl metoduna zəng edərkən tapşırığın yerinə yetirilməsindən sonra vaxt aralığını təyin edə bilərik.
ScheduledExecutorService sch = Executors.newScheduledThreadPool(5); ScheduledFuture sf = sch.schedule(new Callable() { -----code---- }, 5, TimeUnit.SECONDS);
Bir nümunə yaratdıqdan sonra ScheduledExecutorService
, aşağıda göstərilən metodlardan hər hansı birini istifadə edərək bu uyğunluq utilitiyinin tapşırıq icrasını həyata keçirə bilərik.
- cədvəl (Çağırılan tapşırıq, uzun gecikmə, TimeUnit vaxt birliyi)
- cədvəl (Runnable tapşırıq, uzun gecikmə, TimeUnit vaxt birliyi)
- schedAtFixedRate (Runnable, uzun intialGecikmə, uzun müddət, TimeUnit vaxt birliyi)
- schedWithFixedDelay (Runnable, uzun başlanğıc gecikmə, uzun müddət, TimeUnit vaxt birliyi)
ExecutionService-ə bənzər şəkildə, söndürməliyik Planlaşdırılmış İcraçı Xidmət ya istifadə edərək shutdown()
metod və ya shutdownNow()
metodu.
Bloklama Sırası
Bloklama Sırası java.util.concurrent paketinin bir hissəsi olan bir interfeysdir. Eyni zamanda birdən çox mövzuya elementləri növbəyə əlavə edib silməyə imkan verir. Elementlərin daxil edilməsi və silinməsi zamanı ipləri bloklamaq qabiliyyətinə malikdir. Bu, növbədə daha çox element olmadıqda və ən azı 1 element oluncaya qədər gözlədikdə, silmə əməliyyatı zamanı bir mövzuya mane ola biləcəyi deməkdir. Eynilə, növbə maksimum tutuma çatdıqda bir element daxil etməyə çalışdığımız zaman daxiletmə əməliyyatı zamanı bloklanır. BlockingQueue'da bir mövzu həmişə bir element əlavə edərkən digər mövzu elementi növbədən çıxarır.
Elementləri əlavə etmək üçün add () və ya offer () metodlarından istifadə edə və BlockingQueue-dan bir elementi çıxarmaq üçün remove (), take () və ya poll () metodundan istifadə edə bilərik. İlk elementi almaq üçün peek () və ya element () metodundan istifadə edə bilərik.
ArrayBlockingQueue
ArrayBlockingQueue BlockingQueue interfeysini həyata keçirən bir sinifdir. Elementləri daxili olaraq bir sıra şəklində saxlayır. Nöqtənin hazırlanması zamanı yuxarı həddi təyin edə bilərik və bunu sonradan dəyişdirə bilmərik.
BlockingQueue bq = new ArrayBlockingQueue(1024);
Gecikmə növbəsi
The Gecikmə növbəsi sinif BlockingQueue interfeysini həyata keçirir. Bu sinif, göstərilən vaxt gecikməsinin bitməsinə qədər elementləri bloklayır. DelayQueue sinifindən istifadə etmək üçün elementlər java.util.concurrent.Delayed interfeysini tətbiq etməlidirlər.
LinkedBlockingQueue
The LinkedBlockingQueue sinif BlockingQueue interfeysini də həyata keçirir. Elementləri daxili bir LinkedList quruluşu şəklində saxlayır və FIFO (FirstInFirstOut) saxlayır. Bu, baş elementlərinin əvvəlcə daxil etdiyimiz, quyruq elementinin isə daxil etdiyimiz son elementi təmsil etməsi deməkdir.
BlockingQueue bq = new LinkedBlockingQueue();
PriorityBlockingQueue
The PriorityBlockingQueue sinif BlockingQueue interfeysini həyata keçirir. Funksionallıq java.util.PriorityQueue ilə eynidır. Müqayisəli interfeysi tətbiq etmək bütün elementlər üçün məcburidir. Müqayisə edilə bilən interfeysdəki tətbiqetmə əsasında elementləri müvafiq olaraq sifariş edir.
BlockingQueue bq = new PriorityBlockingQueue();
Sinxron Sual
The Sinxron Sual sinif BlockingQueue interfeysini həyata keçirir. Hər dəfə yalnız bir element mübadiləsinə imkan verir. Bu o deməkdir ki, mövzu başqa bir element növbədən kənarlaşdırana qədər bir element daxil etməyi gözləməlidir. Saxlayır sinxronizasiya elə bir şəkildə ki, bir mövzu növbə boş olduqda bir elementi silməyə çalışarkən növbəyə bir element daxil olana qədər bloklaşacaq.
Qadağan etmə rejimi
The Qadağan etmə rejimi java.util.concurrent paketinin bir hissəsi olan bir interfeysdir. Deque təmsil edir və bu cür əməliyyatlar mümkün deyilsə elementlərin daxil edilməsinə və ya çıxarılmasına mane olur. Deque mənasını verir Cüt Uçlu Sıra. Bu, hər iki ucdan elementlər əlavə edib silə biləcəyimiz deməkdir.
LinkedBlockingDeque
The LinkedBlockingDeque sinif BlockingDeque interfeysini həyata keçirir. Hər iki ucdan da yerləşdirmə və silmə əməliyyatlarını dəstəkləyən cüt uclu bir növbəni təmsil edir.
BlockingDeque dq = new LinkedBlockingDeque();
Çağırılan və gələcək
Java Callable və Future interfeysləri çox işləməli konsepsiyada ümumi bir anlayışdır. Bunu əsasən mövzuların bəzi dəyərləri qaytarmasını istədikdə istifadə edə bilərik. Bu paralelliyin bir hissəsidir paketi java.util.concurrent və Java 5-dən etibarən mövcuddur. Çağırılan tapşırıqların vəziyyətini tapmaq üçün Gələcək obyektindən istifadə edə bilərik. Çağırılan tapşırıqlar gələcək bir obyekt qaytarır.
CountdownLatch
The CountdownLatch java.util.concurrent paketinin bir hissəsidir, başqa bir əməliyyat tamamlanana qədər bir qrup mövzuları bloklayır. CountDownLatch-ı hər dəfə countDown () metodunu çağırdığımızda azalacaq bir sayğac dəyəri ilə başlatmalıyıq. Bu sayğac dəyəri 0-a çatdıqda, digər mövzular da buraxılır.
CountDownLatch cd = new CountDownLatch(int counter);
Cyclic Barrier
Cyclic Barrier ipləri sinxronlaşdırdığı və ya maneə rolunu oynadığı sinxronizasiyanı həyata keçirir. Bu o deməkdir ki, bütün iplərin işinə davam etmədən əvvəl bu baryeri gözləməsi və ya keçməsi lazımdır. Bunun üçün istifadə edir await()
üsulu CyclicBarrier. Bütün iplər bu baryerə çatdıqdan sonra davam edə və icrasına davam edə bilər.
CyclicBarrier cb = new CyclicBarrier(int count); cb.await();
Eşzamanlı Xəritə
ConcurrentMap, Map strukturunu təmsil etdiyi java.util.concurrent paketinin bir hissəsi olan bir interfeysdir. Xəritə interfeysində mövcud olan metodlardan başqa öz metodlarına malikdir. Bir interfeys olduğundan funksionallığı tətbiq etməliyik və bu səbəbdən ConcurrentHashMap istifadə edə bilərik.
ConcurrentMap cm = new ConcurrentHashMap(); cm.put("key","value");
ParalelNavigable Map
ConcurrentNavigableMap, NaviagableMap quruluşunu təmsil etdiyi java.util.concurrent paketinin bir hissəsi olan bir interfeysdir. HeadMap (), tailMap () istifadə etdiyimiz alt xəritələr üçün paralel girişi dəstəkləyir.
ConcurrentNavigableMap cn = new ConcurrentSkipListMap();
Mübadilə
Eşanjör, iki ipin bir-biri ilə obyekt mübadiləsi edə biləcəyi bir qab kimi fəaliyyət göstərir. Java.util.concurrent paketində mövcuddur. Mövzular istifadə edərək obyektləri mübadilə edə bilər exchange()
metodu.
Exchanger ex = new Exchanger();
ThreadPoolExecution
ThreadPoolExecution ExecutionService üçün bir tətbiq təmin edir. Birləşdirilmiş mövzuları istifadə edərək Callable və ya Runnable tapşırıqlarını yerinə yetirir. Bir iplik hovuzunda N sayda iplik ola bilər və ölçüsünü corePoolSize
or maximumPoolSize
dəyişənlər.
ForkJoinPool
Java.util.concurrent paketində olan ForkJoinPool tapşırıqları bölməyə kömək edir və alt tapşırıqları eyni vaxtda yerinə yetirməyə imkan verir. Bütün alt tapşırıqlar icrası tamamladıqdan sonra yenidən birləşir. Bu proses iki addımdan ibarətdir: yaba(tapşırığı bölmək) və qoşulmaq(alt tapşırığı birləşdirin). ForkJoinPool Java 7-dən etibarən mövcuddur.
ForkJoinPool fp = new ForkJoinPool(int count);
Kilidlər
Kilid yalnız hazırda icra olunan mövzuda paylaşılan mənbəyə girişin olmasını təmin edir və cari mövzu mənbəyi buraxana qədər digər mövzuların ona daxil olmasını maneə törədir. Bu, əsasən sinxronizasiya üçün istifadə olunur və ayrı-ayrı metodlarda bir kilid () və açma () kimi metodlardan istifadə edə bilərik. Yarış şərtlərinin və kritik hissələrin qarşısını almaq üçün istifadə olunur. Kilid yaratmaq üçün Kilid interfeysini təyin edən bir sinif yaratmalıyıq. The lock()
üsul obyekt və kilidləri unlock()
metod obyektin kilidini açar. Resurs kilidləndikdən sonra hər zaman kritik bölmələrdən istifadə etmək təhlükəsizdir.
ReentrantLocks
Yenidən kilidləmə, Kilidləmə interfeysinin bir tətbiqidir. Mövzunun eyni mənbəni bir neçə dəfə kilidləməsini istədikdə yenidən açılmış kilidlərdən istifadə edə bilərik. Yenidən daxil olan kilidlərdən istifadə edərkən, kilidləmə () metodunu çağırdığımızda sayma dəyərini daxili olaraq artırır və açma () metodunu çağırdıqda dəyəri azaldır.
Lock l = new ReentrantLock(); try { l.lock(); //critical section } finally{ l.unlock(); }
Yenidən qıfıllar paralelliyi tətbiq edərkən faydalıdır. Reentrant kilidinin özünəməxsus üsulları var isLocked()
, getHoldCount()
və s. Ayrı-ayrı təlimlərdə ətraflı şəkildə görəcəyik.
ReadWriteLocks
ReadWriteLocks bir çox mövzuda oxunuş üçün kiliddən istifadə etməyə imkan verir, lakin yazmaq üçün yalnız bir kilid verir. ReadLock və WriteLock tətbiq etmək üçün müəyyən qaydalar mövcuddur.
ReadLock: Başqa heç bir mövzu bir WriteLock istifadə etmədikdə və ya bir WriteLock tələb etmədikdə birdən çox mövzu bir ReadLock əldə edə bilər.
WriteLock: Oxuyan və ya yazan başqa mövzu olmadığı anda yalnız bir mövzu WriteLock əldə edə bilər.
Semafore
Semafor, kritik bölmələrə mövzu girişini bloklamaq üçün istifadə olunan Java paralel proqramlarından biridir. Mövzu kritik hissəyə girməmişdən əvvəl semaforun icazəsi olub olmadığını yoxlayır. İcazə varsa, ipin başqa bir şəkildə daxil olmasına imkan verir. Mövcud icazə sayını yoxlamaq üçün bir metod ehtiva edir. Semaforlar iplik siqnalı üçün də istifadə edilə bilər.
- Semaforun sayılması: Bu tip semafor istifadə edərək göndərilən siqnalların sayını hesablaya bilər
take()
metodu. - Məhdud semafor: Saxlaya biləcəyi siqnal sayının yuxarı sərhədinə sahib olan semafordur
Semaforun 2 əsas metodu var: acquire()
və release()
. Nə vaxt zəng etsək acquire()
üsulu nəzərə alsaq, bir icazə nəzərə alınır və nə vaxt müraciət edirik release()
üsulu sayma semaforuna icazəni geri qaytarır.
ThreadFactory
Bir ThreadFactory lazım olduqda bir mövzu hovuzu yaratmağa kömək edir. İstifadə edərək bir mövzu hovuzunda yeni bir mövzu yarada bilərik newThread(Runnable r)
iş vaxtında metod.
Phaser
Phaser eyni zamanda icra üçün birdən çox sapı bloklayan çevik bir maneədir. Ayrı-ayrı mərhələlərdə bir sıra mövzuları dinamik şəkildə icra edir. CyclicBarrier və CountDownLatch ilə müqayisədə daha yaxşı çevik bir yanaşmadır.
Atom
The atom interfeys kimi atom əməliyyatlarını dəstəkləmək üçün müxtəlif sinifləri təmin edən java.util.concurrent paketinin bir hissəsidir. compareAndSet()
. Aşağıda göstərildiyi kimi müxtəlif siniflərə malikdir:
- AtomicInteger: Atom oxumaq və yazmaq üçün tam dəyişən təmin edir
- AtomicLong: atomik oxumaq və yazmaq üçün Long dəyişənini təmin edir
- AtomicBoolean: Atom oxumaq və yazmaq üçün bir boolean dəyişən təmin edir
- AtomicReference: Atom oxumaq və yazmaq üçün bir obyekt istinad dəyişənini təmin edir
- AtomicStampedReference: atom oxumaq və yazmaq üçün bir obyekt istinad dəyişkənliyi təmin edir
- AtomicIntegerArray: Atom əməliyyatlarını yerinə yetirmək üçün bir sıra tam dəyərlər məcmuəsini təmsil edir
- AtomicLongArray: Atomluq üçün uzun dəyərlər seriyasını təmsil edir
- AtomicReferenceArray: Bir sıra istinad dəyişkənlərini təmsil edir