Բազմահոսքայնությունը Java-ում


== Ներածություն ==
Բազմահոսքայնությունը ծրագրավորման տեխնոլոգիա է, որը հնարավորություն է տալիս ծրագրում ունենալ
2 և ավելի կտորներ, որոնք կարող են իրագործվել միաժամանակ՝ նույն ռեսուրսի հետ աշխատելու
հնարավորությամբ։ Ամեն մի կտոր կարող է լուծել տարբեր խնդիր,
դրանով հասանելի ռեսուրսների (օրինակ՝ մի քանի պրոցեսորի առկայություն) օգտագործումը
դարձնելով ավելի օպտիմալ։
Մի քանի պրոցեսների կողմից ընդհանուր ռեսուրսի կիսելը կոչվում է բազմախնդրություն (multitasking)։
Բազմահոսքայնությունը ընդլայնում է բազմախնդրության գաղափարը և հնարավորություն է ստեղծում,
բացի ՕՀ-ում զուգահեռ աշխատող ծրագրերից (պրոցեսներից), ունենալ նաև զուգահեռ ընթացող
հոսքեր՝ մի ծրագրի մեջ։


== Հոսքերի առաջնայնությունը ==
Java լեզվում ցանկացած հոսք ունի իր առաջնայնությունը, որը օգնում է ՕՀ-ին սահմանել
դրանց իրագործման հերթականությունը։ Այդ առաջնայնությունը որոշվում է 1-10 միջակայքի թվերով,
որը հոսք ստեղծելուց չնշելու դեպքում ավտոմատ կլինի 5։
Սակայն այնուամենայնիվ 100 տոկոսով երաշխավորված չէ, թե ինչ հերթականությամբ կիրագործվեն
հոսքերը։ Այն հիմնականում կախված է ՕՀ-ի տեսակից։


== Իրականացում ==
Java-ում դասը որպես հոսք իրագործելու համար տվյալ դասը պետք է իրականացնի Runnable ինտերֆեյսը՝
ահմանելով վերջինիս կողմից հայտարարված run մեթոդը, կամ ժառանգի Thread դասից և
վերասահմանի
public void run()
public void start()
մեթոդները։
Հոսքը սկսելու համար պետք է կանչել start() մեթոդը։

Thread դասից ժառանգելու օրինակ

Գործնականում այս երկու ձևերից ավելի նախընտրելի է առաջինը, քանի որ ժառանգում օգտագործվում է
որևէ ֆունկցիոնալություն վերասահմանելու համար, ինչի անհրաժեշտությունը չլինելու դեպքում բավական է
պարզապես իրականացնել Runnable ինտերֆեյսը։ Դա նաև հնարավորություն կտա իրականացնող դասին
ծառանգել մեկ այլ դասից, քանի որ Java լեզուն չի տալիս բազմակի ժառանգման հնարավորություն, բայց
թույլատրում է դասին իրականացնել ցանկացած թվով ինտերֆեյսներ միաժամանակ ժառանգելով մեկ դասից։


== Մի քանի հոսքով ծրագրի օրինակ ==
Ստորև նշված օրինակում ստեղծված է 3 հոսք՝

RunnableThread հոսքի run() մեթոդում կանչված է sleep() մեթոդը, որը դադարեցնում է հոսքի աշխատանքը որոշ ժամանակով։ 
Երբ t1–ը կասեցվում է, t2–ը սկսում է իր աշխատանքը։ Ինչպես նաև t2–ը կանչում է join() մեթոդը, որը ստիպում է
ընթացիկ հոսքին սպասել մինչև t2–ի ավարտը։ t2–ի ավարտվելուն պես իր աշխատանքն է սկսում t3–ը։


== Կյանքի փուլերը ==
Հոսքը իր կյանքի ընթացքում կարող է լինել հետևյալ վեց վիճակներում՝


== Հոսքերի ժամանակավոր դադարեցում ==
Հոսքի աշխատանքը դադարեցնելու համար կարելի է տվյալ հոսքի հղումին վերագրել null

Հոսքի աշխատանքը դադարեցնելու համար խորհուրդ չի տրվում օգտվել լեզվի ստանդարտից հեռացված stop() մեթոդից։
Այս մեթոդի կանչը հանգեցնում է տվյալ հոսքի կողմից արգելափակված բոլոր հոսքերի բացվելուն։
Հոսքի աշխատանքը որոշակի ժամանակով դադարեցնելու «հոսքը քնեցնելու» համար օգտագործվում է Thread.sleep() մեթոդը։

Վերը նշված օրինակում մեթոդին տրված արգումենտը իրենից ներկայացնում է այն միլիվայրկյանների քանակը, որքան որ պետք է հոսքը քնի։
Քնի ռեժիմից հոսքին հանելու համար անհրաժեշտ է կանչել interrupt() մեթոդը։


== Հոսքերի սինխրոնացում ==
Ծրագրում երկու և ավելի հոսքերի առկայության դեպքում կարող է ստեղծվել մի իրադրություն, որում երկու
կամ ավելի հոսք փորձեն դիմել նույն ռեսուրսին կամ փոփոխել այն, ինչը կհանգեցնի անցանկալի արդյունքի։
Օրինակ երկու հոսք կարող են գրել նույն ֆայլի մեջ։ Նման խնդիրներից խուսապելու համար անհրաժետշ է
սինխրոնիզացնել հոսքերի աշխատանքը այնպես, որ ապահովագրված լինի նման օրինակ տարաձայնությունների
բացակայությունը։
Ջավայում դա իրականացված է օգտագործելով մոնիտորների գաղափարը։
Ցանկացած օբյեկտ ունի իր հետ ասոցացվող մոնիտոր, որը կարող է արգելափակվել կամ բացվել հոսքի կողմից։
Ժամանակի ցանկացած պահի միայն մեկ հոսք կարող է ունենալ տվյալ օբյեկտի մոնիտորի բանալին։
Ստորև ներկայացված է Ջավայի ծրագրի օրինակ առանց սինխրոնիզացիայի և սինխրոնիզացիայով։

Առաջին դեպքում ծրագիրը ամեն անգամ աշխատացնելուց հետո ստացվում են տարբեր արդյունքներ։
Երկրորդ դեպքում արդյունքները միշտ նույնն են։