Բազմահոսքայնությունը Java-ում
Բազմահոսքայնությունը ծրագրավորման տեխնոլոգիա է, որը հնարավորություն է տալիս ծրագրում ունենալ 2 և ավելի կտորներ, որոնք կարող են իրագործվել միաժամանակ՝ նույն ռեսուրսի հետ աշխատելու հնարավորությամբ։ Ամեն մի կտոր կարող է լուծել տարբեր խնդիր, դրանով հասանելի ռեսուրսների (օրինակ՝ մի քանի պրոցեսորի առկայություն) օգտագործումը դարձնելով ավելի օպտիմալ։ Մի քանի պրոցեսների կողմից ընդհանուր ռեսուրսի կիսելը կոչվում է բազմախնդրություն (multitasking)։ Բազմահոսքայնությունը ընդլայնում է բազմախնդրության գաղափարը և հնարավորություն է ստեղծում, բացի ՕՀ-ում զուգահեռ աշխատող ծրագրերից (պրոցեսներից), ունենալ նաև զուգահեռ ընթացող հոսքեր՝ մի ծրագրի մեջ։ Հոսքերի առաջնայնությունըJava լեզվում ցանկացած հոսք ունի իր առաջնայնությունը, որը օգնում է ՕՀ-ին սահմանել դրանց իրագործման հերթականությունը։ Այդ առաջնայնությունը որոշվում է 1-10 միջակայքի թվերով, որը հոսք ստեղծելուց չնշելու դեպքում ավտոմատ կլինի 5։ Սակայն այնուամենայնիվ 100 տոկոսով երաշխավորված չէ, թե ինչ հերթականությամբ կիրագործվեն հոսքերը։ Այն հիմնականում կախված է ՕՀ-ի տեսակից։ ԻրականացումJava-ում դասը որպես հոսք իրագործելու համար տվյալ դասը պետք է իրականացնի
մեթոդները։ Հոսքը սկսելու համար պետք է կանչել class WikiThread implements Runnable {
private Thread t;
private String threadName;
WikiThread(String name) {
threadName = name;
System.out.println("Creating " + threadName );
}
public void run() {
System.out.println("Running " + threadName );
try {
for(int i = 4; i > 0; --i) {
System.out.println("Thread: " + threadName + ", " + i);
Thread.sleep(50);
}
}
catch (InterruptedException e) {}
System.out.println("Thread " + threadName + " exiting.");
}
public void start() {
System.out.println("Starting " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start();
}
}
}
public class Wiki {
public static void main(String[] args) {
WikiThread R1 = new WikiThread("Thread-1");
R1.start();
WikiThread R2 = new WikiThread("Thread-2");
R2.start();
}
}
Thread դասից ժառանգելու օրինակ class ThreadDemo extends Thread {
private Thread t;
private String threadName;
ThreadDemo( String name) {
threadName = name;
System.out.println("Creating " + threadName );
}
public void run() {
System.out.println("Running " + threadName );
try {
for(int i = 4; i > 0; ––i) {
System.out.println("Thread: " + threadName + ", " + i);
Thread.sleep(50);
}
}
catch (InterruptedException e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start() {
System.out.println("Starting " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start();
}
}
}
public class WikiThread {
public static void main(String args[]) {
ThreadDemo T1 = new ThreadDemo("Thread-1");
T1.start();
ThreadDemo T2 = new ThreadDemo("Thread-2");
T2.start();
}
}
Գործնականում այս երկու ձևերից ավելի նախընտրելի է առաջինը, քանի որ ժառանգում օգտագործվում է
որևէ ֆունկցիոնալություն վերասահմանելու համար, ինչի անհրաժեշտությունը չլինելու դեպքում բավական է
պարզապես իրականացնել Մի քանի հոսքով ծրագրի օրինակՍտորև նշված օրինակում ստեղծված է 3 հոսք՝ RunnableThread հոսքի class RunnableThread implements Runnable {
@Override
public void run() {
try {
System.out.println("Runnable Thread:"+Thread.currentThread().getName());
Thread.sleep(5000);
}
catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread(new RunnableThread());
Thread t2 = new Thread(new RunnableThread());
SingleThread t3 = new SingleThread();
t1.start();
t2.start();
try {
t2.join();
}
catch (InterruptedException e) {
System.out.println(e.getMessage());
}
t3.start();
}
Կյանքի փուլերըՀոսքը իր կյանքի ընթացքում կարող է լինել հետևյալ վեց վիճակներում՝
Հոսքերի ժամանակավոր դադարեցումՀոսքի աշխատանքը դադարեցնելու համար կարելի է տվյալ հոսքի հղումին վերագրել currentThread = null;
Հոսքի աշխատանքը դադարեցնելու համար խորհուրդ չի տրվում օգտվել լեզվի ստանդարտից հեռացված Հոսքի աշխատանքը որոշակի ժամանակով դադարեցնելու «հոսքը քնեցնելու» համար օգտագործվում է Thread.sleep(5000);
Վերը նշված օրինակում մեթոդին տրված արգումենտը իրենից ներկայացնում է այն միլիվայրկյանների քանակը, որքան որ պետք է հոսքը քնի։
Քնի ռեժիմից հոսքին հանելու համար անհրաժեշտ է կանչել Հոսքերի սինխրոնացումԾրագրում երկու և ավելի հոսքերի առկայության դեպքում կարող է ստեղծվել մի իրադրություն, որում երկու կամ ավելի հոսք փորձեն դիմել նույն ռեսուրսին կամ փոփոխել այն, ինչը կհանգեցնի անցանկալի արդյունքի։ Օրինակ երկու հոսք կարող են գրել նույն ֆայլի մեջ։ Նման խնդիրներից խուսապելու համար անհրաժետշ է սինխրոնիզացնել հոսքերի աշխատանքը այնպես, որ ապահովագրված լինի նման օրինակ տարաձայնությունների բացակայությունը։ Ջավայում դա իրականացված է օգտագործելով մոնիտորների գաղափարը։ Ցանկացած օբյեկտ ունի իր հետ ասոցացվող մոնիտոր, որը կարող է արգելափակվել կամ բացվել հոսքի կողմից։ Ժամանակի ցանկացած պահի միայն մեկ հոսք կարող է ունենալ տվյալ օբյեկտի մոնիտորի բանալին։ Ստորև ներկայացված է Ջավայի ծրագրի օրինակ առանց սինխրոնիզացիայի և սինխրոնիզացիայով։ //առանց սինխրոնիզացիա
class PrintDemo {
public void printCount(){
try {
for(int i = 5; i > 0; i--) {
System.out.println("Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd){
threadName = name;
PD = pd;
}
public void run() {
PD.printCount();
System.out.println("Thread " + threadName + " exiting.");
}
public void start ()
{
System.out.println("Starting " + threadName );
if (t == null)
{
t = new Thread (this, threadName);
t.start ();
}
}
}
public class TestThread {
public static void main(String args[]) {
PrintDemo PD = new PrintDemo();
ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD );
ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD );
T1.start();
T2.start();
// wait for threads to end
try {
T1.join();
T2.join();
} catch( Exception e) {
System.out.println("Interrupted");
}
}
}
//սինխրոնիզացիայով
class PrintDemo {
public void printCount(){
try {
for(int i = 5; i > 0; i--) {
System.out.println("Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd){
threadName = name;
PD = pd;
}
public void run() {
synchronized(PD) {
PD.printCount();
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start ()
{
System.out.println("Starting " + threadName );
if (t == null)
{
t = new Thread (this, threadName);
t.start ();
}
}
}
public class TestThread {
public static void main(String args[]) {
PrintDemo PD = new PrintDemo();
ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD );
ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD );
T1.start();
T2.start();
// wait for threads to end
try {
T1.join();
T2.join();
} catch( Exception e) {
System.out.println("Interrupted");
}
}
}
Առաջին դեպքում ծրագիրը ամեն անգամ աշխատացնելուց հետո ստացվում են տարբեր արդյունքներ։ Երկրորդ դեպքում արդյունքները միշտ նույնն են։ |