పరిచయం
కాబట్టి, జావాలో థ్రెడ్లు ఉన్నాయని మనకు తెలుసు. మీరు బెటర్ టుగెదర్: జావా మరియు థ్రెడ్ క్లాస్ అనే రివ్యూలో దాని గురించి చదువుకోవచ్చు . పార్ట్ I - అమలు యొక్క థ్రెడ్లు . పనిని సమాంతరంగా నిర్వహించడానికి థ్రెడ్లు అవసరం. ఇది థ్రెడ్లు ఒకదానితో ఒకటి పరస్పర చర్య చేసే అవకాశం ఎక్కువగా ఉంటుంది. ఇది ఎలా జరుగుతుందో మరియు మనకు ఏ ప్రాథమిక సాధనాలు ఉన్నాయో చూద్దాం.
దిగుబడి
Thread.yield() అడ్డుగా ఉంది మరియు చాలా అరుదుగా ఉపయోగించబడుతుంది. ఇది ఇంటర్నెట్లో అనేక రకాలుగా వివరించబడింది. థ్రెడ్ ప్రాధాన్యతల ఆధారంగా థ్రెడ్ డౌన్లోడ్ చేయబడే థ్రెడ్ల యొక్క కొంత క్యూ ఉందని వ్రాసే కొంతమంది వ్యక్తులతో సహా. ఇతర వ్యక్తులు ఒక థ్రెడ్ దాని స్థితిని "రన్నింగ్" నుండి "రన్ చేయదగినది"గా మారుస్తుందని వ్రాస్తారు (ఈ హోదాల మధ్య ఎటువంటి వ్యత్యాసం లేనప్పటికీ, జావా వాటి మధ్య తేడాను గుర్తించదు). వాస్తవికత ఏమిటంటే ఇది చాలా తక్కువగా తెలిసినది మరియు ఒక కోణంలో ఇంకా సరళమైనది. పద్ధతి యొక్క డాక్యుమెంటేషన్ కోసం లాగ్ చేయబడిన
yield()
అది చదివితే తెలుస్తుందిyield()
పద్ధతి నిజానికి జావా థ్రెడ్ షెడ్యూలర్కు ఈ థ్రెడ్కు తక్కువ ఎగ్జిక్యూషన్ సమయం ఇవ్వవచ్చని కొన్ని సిఫార్సులను మాత్రమే అందిస్తుంది. కానీ వాస్తవానికి ఏమి జరుగుతుంది, అంటే షెడ్యూలర్ సిఫార్సుపై పని చేస్తుందా మరియు సాధారణంగా అది ఏమి చేస్తుందో అనేది JVM యొక్క అమలు మరియు ఆపరేటింగ్ సిస్టమ్పై ఆధారపడి ఉంటుంది. మరియు ఇది కొన్ని ఇతర కారకాలపై కూడా ఆధారపడి ఉండవచ్చు. జావా భాష అభివృద్ధి చెందినందున మల్టీథ్రెడింగ్ పునరాలోచించబడినందున అన్ని గందరగోళాలు ఎక్కువగా ఉన్నాయి. ఇక్కడ స్థూలదృష్టిలో మరింత చదవండి: Java Thread.yield() కు సంక్షిప్త పరిచయం .
నిద్రించు
ఒక థ్రెడ్ దాని అమలు సమయంలో నిద్రపోవచ్చు. ఇది ఇతర థ్రెడ్లతో సులభతరమైన పరస్పర చర్య. మా జావా కోడ్ను అమలు చేసే జావా వర్చువల్ మెషీన్ను అమలు చేసే ఆపరేటింగ్ సిస్టమ్ దాని స్వంత థ్రెడ్ షెడ్యూలర్ను కలిగి ఉంది . ఇది ఏ థ్రెడ్ను ఎప్పుడు ప్రారంభించాలో నిర్ణయిస్తుంది. ప్రోగ్రామర్ ఈ షెడ్యూలర్తో నేరుగా జావా కోడ్ నుండి ఇంటరాక్ట్ అవ్వలేరు, JVM ద్వారా మాత్రమే. అతను లేదా ఆమె థ్రెడ్ను కాసేపు పాజ్ చేయమని, అంటే దానిని నిద్రపోమని షెడ్యూలర్ని అడగవచ్చు. మీరు ఈ కథనాలలో మరింత చదవవచ్చు: Thread.sleep() మరియు మల్టీథ్రెడింగ్ ఎలా పనిచేస్తుంది . Windows ఆపరేటింగ్ సిస్టమ్లలో థ్రెడ్లు ఎలా పని చేస్తాయో కూడా మీరు తనిఖీ చేయవచ్చు: Windows Thread యొక్క అంతర్గతాలు . మరియు ఇప్పుడు మన స్వంత కళ్ళతో చూద్దాం. ఈ క్రింది కోడ్ని ఫైల్లో సేవ్ చేయండిHelloWorldApp.java
:
class HelloWorldApp {
public static void main(String []args) {
Runnable task = () -> {
try {
int secToWait = 1000 * 60;
Thread.currentThread().sleep(secToWait);
System.out.println("Woke up");
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Thread thread = new Thread(task);
thread.start();
}
}
మీరు చూడగలిగినట్లుగా, మేము 60 సెకన్లపాటు వేచి ఉండే కొన్ని పనిని కలిగి ఉన్నాము, దాని తర్వాత ప్రోగ్రామ్ ముగుస్తుంది. మేము " " ఆదేశాన్ని ఉపయోగించి కంపైల్ చేసి javac HelloWorldApp.java
, ఆపై " " ఉపయోగించి ప్రోగ్రామ్ను అమలు చేస్తాము java HelloWorldApp
. ప్రోగ్రామ్ను ప్రత్యేక విండోలో ప్రారంభించడం మంచిది. ఉదాహరణకు, Windowsలో, ఇది ఇలా ఉంటుంది: start java HelloWorldApp
. PID (ప్రాసెస్ ID)ని పొందడానికి మేము jps ఆదేశాన్ని ఉపయోగిస్తాము మరియు మేము థ్రెడ్ల జాబితాను "తో తెరుస్తాము jvisualvm --openpid pid
: 
try {
TimeUnit.SECONDS.sleep(60);
System.out.println("Woke up");
} catch (InterruptedException e) {
e.printStackTrace();
}
మేము ప్రతిచోటా నిర్వహిస్తున్నామని మీరు గమనించారా InterruptedException
? ఎందుకు అర్థం చేసుకుందాం.
Thread.interrupt()
విషయం ఏమిటంటే, థ్రెడ్ వేచి ఉన్నప్పుడు/నిద్రపోతున్నప్పుడు, ఎవరైనా అంతరాయం కలిగించాలనుకోవచ్చు. ఈ సందర్భంలో, మేము ఒకInterruptedException
. Thread.stop()
పద్ధతి నిలిపివేయబడినది, అంటే పాతది మరియు అవాంఛనీయమైనదిగా ప్రకటించబడిన తర్వాత ఈ విధానం సృష్టించబడింది . కారణం ఏమిటంటే, stop()
పద్ధతిని పిలిచినప్పుడు, థ్రెడ్ కేవలం "చంపబడింది", ఇది చాలా అనూహ్యమైనది. థ్రెడ్ ఎప్పుడు ఆపివేయబడుతుందో మాకు తెలియదు మరియు డేటా స్థిరత్వానికి మేము హామీ ఇవ్వలేము. థ్రెడ్ చంపబడినప్పుడు మీరు ఫైల్కు డేటాను వ్రాస్తున్నారని ఊహించండి. థ్రెడ్ను చంపే బదులు, దానికి అంతరాయం కలిగించాలని చెప్పడం మరింత లాజికల్గా ఉంటుందని జావా సృష్టికర్తలు నిర్ణయించుకున్నారు. ఈ సమాచారంపై ఎలా స్పందించాలనేది తంతు స్వయంగా నిర్ణయించుకోవాల్సిన అంశం. మరిన్ని వివరాల కోసం, Thread.stop ఎందుకు నిలిపివేయబడింది?ఒరాకిల్ వెబ్సైట్లో. ఒక ఉదాహరణ చూద్దాం:
public static void main(String []args) {
Runnable task = () -> {
try {
TimeUnit.SECONDS.sleep(60);
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
};
Thread thread = new Thread(task);
thread.start();
thread.interrupt();
}
ఈ ఉదాహరణలో, మేము 60 సెకన్లు వేచి ఉండము. బదులుగా, మేము వెంటనే "ఇంటరప్టెడ్"ని ప్రదర్శిస్తాము. దీనికి కారణం మేము interrupt()
థ్రెడ్లోని పద్ధతిని పిలిచాము. ఈ పద్ధతి "ఇంటరప్ట్ స్టేటస్" అనే అంతర్గత ఫ్లాగ్ను సెట్ చేస్తుంది. అంటే, ప్రతి థ్రెడ్ నేరుగా యాక్సెస్ చేయని అంతర్గత జెండాను కలిగి ఉంటుంది. కానీ ఈ ఫ్లాగ్తో పరస్పర చర్య చేయడానికి మాకు స్థానిక పద్ధతులు ఉన్నాయి. కానీ అది ఒక్కటే మార్గం కాదు. ఒక థ్రెడ్ రన్ అవుతూ ఉండవచ్చు, దేనికోసం ఎదురుచూడకుండా, కేవలం చర్యలను ప్రదర్శిస్తూ ఉండవచ్చు. కానీ ఇతరులు దాని పనిని ఒక నిర్దిష్ట సమయంలో ముగించాలనుకుంటున్నారని అది ఊహించవచ్చు. ఉదాహరణకి:
public static void main(String []args) {
Runnable task = () -> {
while(!Thread.currentThread().isInterrupted()) {
// Do some work
}
System.out.println("Finished");
};
Thread thread = new Thread(task);
thread.start();
thread.interrupt();
}
ఎగువ ఉదాహరణలో, while
థ్రెడ్ బాహ్యంగా అంతరాయం కలిగించే వరకు లూప్ అమలు చేయబడుతుంది. ఫ్లాగ్ విషయానికొస్తే , మనం ఒక క్యాచ్ చేస్తే , isInterrupted ఫ్లాగ్ రీసెట్ చేయబడుతుందని, ఆపై తప్పుగా తిరిగి వస్తుందని isInterrupted
తెలుసుకోవడం ముఖ్యం . థ్రెడ్ క్లాస్ కూడా స్టాటిక్ Thread.interrupted() పద్ధతిని కలిగి ఉంది, అది ప్రస్తుత థ్రెడ్కు మాత్రమే వర్తిస్తుంది, కానీ ఈ పద్ధతి ఫ్లాగ్ను తప్పుగా రీసెట్ చేస్తుంది! థ్రెడ్ అంతరాయం అనే శీర్షికతో ఈ అధ్యాయంలో మరింత చదవండి . InterruptedException
isInterrupted()
చేరండి (మరొక థ్రెడ్ పూర్తయ్యే వరకు వేచి ఉండండి)
నిరీక్షణ యొక్క సరళమైన రకం మరొక థ్రెడ్ పూర్తయ్యే వరకు వేచి ఉంది.
public static void main(String []args) throws InterruptedException {
Runnable task = () -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
};
Thread thread = new Thread(task);
thread.start();
thread.join();
System.out.println("Finished");
}
ఈ ఉదాహరణలో, కొత్త థ్రెడ్ 5 సెకన్లు నిద్రపోతుంది. అదే సమయంలో, స్లీపింగ్ థ్రెడ్ మేల్కొని దాని పనిని పూర్తి చేసే వరకు ప్రధాన థ్రెడ్ వేచి ఉంటుంది. మీరు JVisualVMలో థ్రెడ్ స్థితిని చూస్తే, అది ఇలా కనిపిస్తుంది: 
join
పద్ధతి చాలా సులభం, ఎందుకంటే ఇది జావా కోడ్తో కూడిన ఒక పద్ధతి, wait()
అది పిలిచే థ్రెడ్ సజీవంగా ఉన్నంత వరకు అమలు చేస్తుంది. థ్రెడ్ చనిపోయిన వెంటనే (దాని పనిని పూర్తి చేసినప్పుడు), నిరీక్షణకు అంతరాయం ఏర్పడుతుంది. మరియు అది పద్ధతి యొక్క మాయాజాలం join()
. కాబట్టి, అత్యంత ఆసక్తికరమైన విషయానికి వెళ్దాం.
మానిటర్
మల్టీథ్రెడింగ్ మానిటర్ భావనను కలిగి ఉంటుంది. మానిటర్ అనే పదం 16వ శతాబ్దపు లాటిన్ ద్వారా ఆంగ్లంలోకి వచ్చింది మరియు దీని అర్థం "ఒక ప్రక్రియ యొక్క నిరంతర రికార్డును పరిశీలించడానికి, తనిఖీ చేయడానికి లేదా ఉంచడానికి ఉపయోగించే పరికరం లేదా పరికరం". ఈ వ్యాసం యొక్క సందర్భంలో, మేము ప్రాథమికాలను కవర్ చేయడానికి ప్రయత్నిస్తాము. వివరాలను కోరుకునే ఎవరికైనా, దయచేసి లింక్ చేయబడిన మెటీరియల్లలోకి ప్రవేశించండి. మేము జావా లాంగ్వేజ్ స్పెసిఫికేషన్ (JLS)తో మా ప్రయాణాన్ని ప్రారంభిస్తాము: 17.1. సమకాలీకరణ . ఇది క్రింది విధంగా చెబుతుంది:
lock()
లేదా విడుదల చేయగలవు unlock()
. తరువాత, మేము ఒరాకిల్ వెబ్సైట్లో ట్యుటోరియల్ని కనుగొంటాము: అంతర్గత లాక్లు మరియు సమకాలీకరణ. ఈ ట్యుటోరియల్ జావా యొక్క సమకాలీకరణ అంతర్గత లాక్ లేదా మానిటర్ లాక్ అని పిలువబడే అంతర్గత అంశం చుట్టూ నిర్మించబడింది . ఈ తాళం తరచుగా " మానిటర్ " అని పిలువబడుతుంది. జావాలోని ప్రతి వస్తువు దానితో అనుబంధించబడిన అంతర్గత లాక్ని కలిగి ఉందని కూడా మనం మళ్లీ చూస్తాము. మీరు జావా - అంతర్గత తాళాలు మరియు సమకాలీకరణను చదవగలరు . తర్వాత జావాలోని ఒక వస్తువు మానిటర్తో ఎలా అనుబంధించబడుతుందో అర్థం చేసుకోవడం ముఖ్యం. జావాలో, ప్రతి వస్తువుకు కోడ్ నుండి ప్రోగ్రామర్కు అందుబాటులో లేని అంతర్గత మెటాడేటాను నిల్వ చేసే హెడర్ ఉంటుంది, అయితే వర్చువల్ మిషన్ ఆబ్జెక్ట్లతో సరిగ్గా పని చేయాల్సి ఉంటుంది. ఆబ్జెక్ట్ హెడర్లో "మార్క్ వర్డ్" ఉంది, ఇది ఇలా కనిపిస్తుంది: 
https://edu.netbeans.org/contrib/slides/java-overview-and-java-se6.pdf
public class HelloWorld{
public static void main(String []args){
Object object = new Object();
synchronized(object) {
System.out.println("Hello World");
}
}
}
ఇక్కడ, ప్రస్తుత థ్రెడ్ (ఈ పంక్తులు కోడ్ అమలు చేయబడినది) synchronized
దానితో అనుబంధించబడిన మానిటర్ను ఉపయోగించడానికి ప్రయత్నించడానికి కీవర్డ్ని ఉపయోగిస్తుందిobject"\
లాక్ని పొందడానికి/పొందడానికి వేరియబుల్. మానిటర్ కోసం మరెవరూ పోటీ చేయనట్లయితే (అంటే మరెవరూ ఒకే వస్తువును ఉపయోగించి సమకాలీకరించబడిన కోడ్ను అమలు చేయడం లేదు), అప్పుడు జావా "బయాస్డ్ లాకింగ్" అనే ఆప్టిమైజేషన్ను నిర్వహించడానికి ప్రయత్నించవచ్చు. ఆబ్జెక్ట్ హెడర్లోని మార్క్ వర్డ్కు సంబంధిత ట్యాగ్ మరియు మానిటర్ లాక్ని ఏ థ్రెడ్ కలిగి ఉందనే దాని గురించిన రికార్డ్ జోడించబడతాయి. ఇది మానిటర్ను లాక్ చేయడానికి అవసరమైన ఓవర్హెడ్ను తగ్గిస్తుంది. మానిటర్ ఇంతకుముందు మరొక థ్రెడ్ యాజమాన్యంలో ఉంటే, అటువంటి లాకింగ్ సరిపోదు. JVM తదుపరి లాకింగ్ రకంకి మారుతుంది: "ప్రాథమిక లాకింగ్". ఇది కంపేర్-అండ్-స్వాప్ (CAS) ఆపరేషన్లను ఉపయోగిస్తుంది. ఇంకా ఏమిటంటే, ఆబ్జెక్ట్ హెడర్ యొక్క మార్క్ వర్డ్ ఇకపై మార్క్ పదాన్ని నిల్వ చేయదు, కానీ అది ఎక్కడ నిల్వ చేయబడిందో సూచించబడుతుంది మరియు ట్యాగ్ మారుతుంది, తద్వారా మనం ప్రాథమిక లాకింగ్ని ఉపయోగిస్తున్నామని JVM అర్థం చేసుకుంటుంది. ఒక మానిటర్ కోసం బహుళ థ్రెడ్లు పోటీ పడితే (ఒకటి లాక్ని పొంది, రెండవది లాక్ విడుదల కోసం వేచి ఉంది), అప్పుడు మార్క్ వర్డ్లోని ట్యాగ్ మారుతుంది మరియు మార్క్ వర్డ్ ఇప్పుడు మానిటర్కు సూచనను నిల్వ చేస్తుంది ఒక వస్తువుగా — JVM యొక్క కొంత అంతర్గత అంశం. JDK ఎన్చాన్స్మెంట్ ప్రతిపాదన (JEP)లో పేర్కొన్నట్లుగా, ఈ పరిస్థితికి ఈ ఎంటిటీని నిల్వ చేయడానికి మెమరీ యొక్క స్థానిక హీప్ ప్రాంతంలో స్థలం అవసరం. ఈ అంతర్గత ఎంటిటీ యొక్క మెమరీ స్థానానికి సంబంధించిన సూచన ఆబ్జెక్ట్ హెడర్ యొక్క మార్క్ వర్డ్లో నిల్వ చేయబడుతుంది. అందువల్ల, మానిటర్ అనేది బహుళ థ్రెడ్ల మధ్య భాగస్వామ్య వనరులకు యాక్సెస్ను సమకాలీకరించడానికి ఒక మెకానిజం. JVM ఈ మెకానిజం యొక్క అనేక అమలుల మధ్య మారుతుంది. కాబట్టి, సరళత కోసం, మానిటర్ గురించి మాట్లాడేటప్పుడు, మేము వాస్తవానికి తాళాల గురించి మాట్లాడుతున్నాము. మరియు లాక్ విడుదల కావడానికి ఒక సెకను వేచి ఉంది), ఆపై మార్క్ వర్డ్లోని ట్యాగ్ మారుతుంది మరియు మార్క్ వర్డ్ ఇప్పుడు మానిటర్కు సూచనను ఒక వస్తువుగా నిల్వ చేస్తుంది — JVM యొక్క కొంత అంతర్గత అంశం. JDK ఎన్చాన్స్మెంట్ ప్రతిపాదన (JEP)లో పేర్కొన్నట్లుగా, ఈ పరిస్థితికి ఈ ఎంటిటీని నిల్వ చేయడానికి మెమరీ యొక్క స్థానిక హీప్ ప్రాంతంలో స్థలం అవసరం. ఈ అంతర్గత ఎంటిటీ యొక్క మెమరీ స్థానానికి సంబంధించిన సూచన ఆబ్జెక్ట్ హెడర్ యొక్క మార్క్ వర్డ్లో నిల్వ చేయబడుతుంది. అందువల్ల, మానిటర్ అనేది బహుళ థ్రెడ్ల మధ్య భాగస్వామ్య వనరులకు యాక్సెస్ను సమకాలీకరించడానికి ఒక మెకానిజం. JVM ఈ మెకానిజం యొక్క అనేక అమలుల మధ్య మారుతుంది. కాబట్టి, సరళత కోసం, మానిటర్ గురించి మాట్లాడేటప్పుడు, మేము వాస్తవానికి తాళాల గురించి మాట్లాడుతున్నాము. మరియు లాక్ విడుదల కావడానికి ఒక సెకను వేచి ఉంది), ఆపై మార్క్ వర్డ్లోని ట్యాగ్ మారుతుంది మరియు మార్క్ వర్డ్ ఇప్పుడు మానిటర్కు సూచనను ఒక వస్తువుగా నిల్వ చేస్తుంది — JVM యొక్క కొంత అంతర్గత అంశం. JDK ఎన్చాన్స్మెంట్ ప్రతిపాదన (JEP)లో పేర్కొన్నట్లుగా, ఈ పరిస్థితికి ఈ ఎంటిటీని నిల్వ చేయడానికి మెమరీ యొక్క స్థానిక హీప్ ప్రాంతంలో స్థలం అవసరం. ఈ అంతర్గత ఎంటిటీ యొక్క మెమరీ స్థానానికి సంబంధించిన సూచన ఆబ్జెక్ట్ హెడర్ యొక్క మార్క్ వర్డ్లో నిల్వ చేయబడుతుంది. అందువల్ల, మానిటర్ అనేది బహుళ థ్రెడ్ల మధ్య భాగస్వామ్య వనరులకు యాక్సెస్ను సమకాలీకరించడానికి ఒక మెకానిజం. JVM ఈ మెకానిజం యొక్క అనేక అమలుల మధ్య మారుతుంది. కాబట్టి, సరళత కోసం, మానిటర్ గురించి మాట్లాడేటప్పుడు, మేము వాస్తవానికి తాళాల గురించి మాట్లాడుతున్నాము. మరియు మార్క్ వర్డ్ ఇప్పుడు మానిటర్కు సూచనను ఒక వస్తువుగా నిల్వ చేస్తుంది — JVM యొక్క కొంత అంతర్గత అంశం. JDK ఎన్చాన్స్మెంట్ ప్రతిపాదన (JEP)లో పేర్కొన్నట్లుగా, ఈ పరిస్థితికి ఈ ఎంటిటీని నిల్వ చేయడానికి మెమరీ యొక్క స్థానిక హీప్ ప్రాంతంలో స్థలం అవసరం. ఈ అంతర్గత ఎంటిటీ యొక్క మెమరీ స్థానానికి సంబంధించిన సూచన ఆబ్జెక్ట్ హెడర్ యొక్క మార్క్ వర్డ్లో నిల్వ చేయబడుతుంది. అందువల్ల, మానిటర్ అనేది బహుళ థ్రెడ్ల మధ్య భాగస్వామ్య వనరులకు యాక్సెస్ను సమకాలీకరించడానికి ఒక మెకానిజం. JVM ఈ మెకానిజం యొక్క అనేక అమలుల మధ్య మారుతుంది. కాబట్టి, సరళత కోసం, మానిటర్ గురించి మాట్లాడేటప్పుడు, మేము వాస్తవానికి తాళాల గురించి మాట్లాడుతున్నాము. మరియు మార్క్ వర్డ్ ఇప్పుడు మానిటర్కు సూచనను ఒక వస్తువుగా నిల్వ చేస్తుంది — JVM యొక్క కొంత అంతర్గత అంశం. JDK ఎన్చాన్స్మెంట్ ప్రతిపాదన (JEP)లో పేర్కొన్నట్లుగా, ఈ పరిస్థితికి ఈ ఎంటిటీని నిల్వ చేయడానికి మెమరీ యొక్క స్థానిక హీప్ ప్రాంతంలో స్థలం అవసరం. ఈ అంతర్గత ఎంటిటీ యొక్క మెమరీ స్థానానికి సంబంధించిన సూచన ఆబ్జెక్ట్ హెడర్ యొక్క మార్క్ వర్డ్లో నిల్వ చేయబడుతుంది. అందువల్ల, మానిటర్ అనేది బహుళ థ్రెడ్ల మధ్య భాగస్వామ్య వనరులకు యాక్సెస్ను సమకాలీకరించడానికి ఒక మెకానిజం. JVM ఈ మెకానిజం యొక్క అనేక అమలుల మధ్య మారుతుంది. కాబట్టి, సరళత కోసం, మానిటర్ గురించి మాట్లాడేటప్పుడు, మేము వాస్తవానికి తాళాల గురించి మాట్లాడుతున్నాము. ఈ అంతర్గత ఎంటిటీ యొక్క మెమరీ స్థానానికి సంబంధించిన సూచన ఆబ్జెక్ట్ హెడర్ యొక్క మార్క్ వర్డ్లో నిల్వ చేయబడుతుంది. అందువల్ల, మానిటర్ అనేది బహుళ థ్రెడ్ల మధ్య భాగస్వామ్య వనరులకు యాక్సెస్ను సమకాలీకరించడానికి ఒక మెకానిజం. JVM ఈ మెకానిజం యొక్క అనేక అమలుల మధ్య మారుతుంది. కాబట్టి, సరళత కోసం, మానిటర్ గురించి మాట్లాడేటప్పుడు, మేము వాస్తవానికి తాళాల గురించి మాట్లాడుతున్నాము. ఈ అంతర్గత ఎంటిటీ యొక్క మెమరీ స్థానానికి సంబంధించిన సూచన ఆబ్జెక్ట్ హెడర్ యొక్క మార్క్ వర్డ్లో నిల్వ చేయబడుతుంది. అందువల్ల, మానిటర్ అనేది బహుళ థ్రెడ్ల మధ్య భాగస్వామ్య వనరులకు యాక్సెస్ను సమకాలీకరించడానికి ఒక మెకానిజం. JVM ఈ మెకానిజం యొక్క అనేక అమలుల మధ్య మారుతుంది. కాబట్టి, సరళత కోసం, మానిటర్ గురించి మాట్లాడేటప్పుడు, మేము వాస్తవానికి తాళాల గురించి మాట్లాడుతున్నాము. 
సమకాలీకరించబడింది (లాక్ కోసం వేచి ఉంది)
మనం ఇంతకు ముందు చూసినట్లుగా, "సింక్రొనైజ్డ్ బ్లాక్" (లేదా "క్రిటికల్ సెక్షన్") భావన మానిటర్ భావనతో దగ్గరి సంబంధం కలిగి ఉంటుంది. ఒక ఉదాహరణను పరిశీలించండి:
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
Runnable task = () -> {
synchronized(lock) {
System.out.println("thread");
}
};
Thread th1 = new Thread(task);
th1.start();
synchronized(lock) {
for (int i = 0; i < 8; i++) {
Thread.currentThread().sleep(1000);
System.out.print(" " + i);
}
System.out.println(" ...");
}
}
ఇక్కడ, ప్రధాన థ్రెడ్ మొదట టాస్క్ ఆబ్జెక్ట్ను కొత్త థ్రెడ్కు పంపుతుంది, ఆపై వెంటనే లాక్ని పొందుతుంది మరియు దానితో (8 సెకన్లు) సుదీర్ఘ ఆపరేషన్ చేస్తుంది. ఈ సమయంలో, టాస్క్ కొనసాగడం సాధ్యం కాదు, ఎందుకంటే ఇది బ్లాక్లోకి ప్రవేశించదు synchronized
, ఎందుకంటే లాక్ ఇప్పటికే కొనుగోలు చేయబడింది. థ్రెడ్ లాక్ని పొందలేకపోతే, అది మానిటర్ కోసం వేచి ఉంటుంది. ఇది లాక్ని పొందిన వెంటనే, అది అమలును కొనసాగిస్తుంది. థ్రెడ్ మానిటర్ నుండి నిష్క్రమించినప్పుడు, అది లాక్ని విడుదల చేస్తుంది. JVisualVMలో, ఇది ఇలా కనిపిస్తుంది: 
th1.getState()
for లూప్లోని స్టేట్మెంట్ బ్లాక్ చేయబడింది అని తిరిగి వస్తుంది , ఎందుకంటే లూప్ నడుస్తున్నంత కాలం, lock
ఆబ్జెక్ట్ యొక్క మానిటర్ థ్రెడ్చే ఆక్రమించబడుతుంది main
మరియు th1
థ్రెడ్ బ్లాక్ చేయబడుతుంది మరియు లాక్ విడుదలయ్యే వరకు కొనసాగదు. సమకాలీకరించబడిన బ్లాక్లతో పాటు, మొత్తం పద్ధతిని సమకాలీకరించవచ్చు. ఉదాహరణకు, HashTable
తరగతి నుండి ఇక్కడ ఒక పద్ధతి ఉంది:
public synchronized int size() {
return count;
}
ఈ పద్ధతి ఏ సమయంలోనైనా ఒక థ్రెడ్ ద్వారా మాత్రమే అమలు చేయబడుతుంది. మనకు నిజంగా తాళం అవసరమా? అవును, మాకు ఇది అవసరం. ఉదాహరణ పద్ధతుల విషయంలో, "ఈ" వస్తువు (ప్రస్తుత వస్తువు) లాక్ వలె పనిచేస్తుంది. ఈ అంశంపై ఇక్కడ ఆసక్తికరమైన చర్చ ఉంది: సమకాలీకరించబడిన బ్లాక్కు బదులుగా సమకాలీకరించబడిన పద్ధతిని ఉపయోగించడం వల్ల ప్రయోజనం ఉందా? . పద్ధతి స్థిరంగా ఉంటే, లాక్ "ఈ" ఆబ్జెక్ట్ కాదు (ఎందుకంటే స్టాటిక్ పద్ధతికి "ఈ" ఆబ్జెక్ట్ ఉండదు), కానీ క్లాస్ ఆబ్జెక్ట్ (ఉదాహరణకు, ) Integer.class
.
వేచి ఉండండి (మానిటర్ కోసం వేచి ఉంది). notify() మరియు notifyAll() పద్ధతులు
థ్రెడ్ క్లాస్ మానిటర్తో అనుబంధించబడిన మరొక నిరీక్షణ పద్ధతిని కలిగి ఉంది.sleep()
మరియు కాకుండా join()
, ఈ పద్ధతిని కేవలం పిలవలేము. దాని పేరు wait()
. wait
మేము వేచి ఉండాలనుకుంటున్న మానిటర్తో అనుబంధించబడిన వస్తువుపై పద్ధతిని పిలుస్తారు . ఒక ఉదాహరణ చూద్దాం:
public static void main(String []args) throws InterruptedException {
Object lock = new Object();
// The task object will wait until it is notified via lock
Runnable task = () -> {
synchronized(lock) {
try {
lock.wait();
} catch(InterruptedException e) {
System.out.println("interrupted");
}
}
// After we are notified, we will wait until we can acquire the lock
System.out.println("thread");
};
Thread taskThread = new Thread(task);
taskThread.start();
// We sleep. Then we acquire the lock, notify, and release the lock
Thread.currentThread().sleep(3000);
System.out.println("main");
synchronized(lock) {
lock.notify();
}
}
JVisualVMలో, ఇది ఇలా కనిపిస్తుంది: 
wait()
మరియు notify()
పద్ధతులు తో అనుబంధించబడి ఉన్నాయని గుర్తుంచుకోండి java.lang.Object
. థ్రెడ్-సంబంధిత పద్ధతులు తరగతిలో ఉండటం వింతగా అనిపించవచ్చు Object
. అయితే దానికి కారణం ఇప్పుడు బయటపడింది. జావాలోని ప్రతి వస్తువుకు హెడర్ ఉందని మీరు గుర్తుంచుకుంటారు. హెడర్ మానిటర్ గురించిన సమాచారంతో సహా వివిధ గృహనిర్వాహక సమాచారాన్ని కలిగి ఉంటుంది, అనగా లాక్ స్థితి. గుర్తుంచుకోండి, ప్రతి వస్తువు లేదా తరగతి యొక్క ఉదాహరణ, అంతర్గత లాక్ లేదా మానిటర్ అని పిలువబడే JVMలోని అంతర్గత అంశంతో అనుబంధించబడి ఉంటుంది. పై ఉదాహరణలో, టాస్క్ ఆబ్జెక్ట్ కోసం కోడ్ మేము ఆబ్జెక్ట్తో అనుబంధించబడిన మానిటర్ కోసం సమకాలీకరించబడిన బ్లాక్ని నమోదు చేసామని సూచిస్తుంది lock
. మేము ఈ మానిటర్ కోసం లాక్ని పొందడంలో విజయవంతమైతే, అప్పుడుwait()
అంటారు. విధిని అమలు చేసే థ్రెడ్ lock
ఆబ్జెక్ట్ యొక్క మానిటర్ను విడుదల చేస్తుంది, కానీ ఆబ్జెక్ట్ యొక్క మానిటర్ నుండి నోటిఫికేషన్ కోసం వేచి ఉన్న థ్రెడ్ల క్యూలోకి ప్రవేశిస్తుంది lock
. ఈ థ్రెడ్ల క్యూని WAIT SET అని పిలుస్తారు, ఇది దాని ప్రయోజనాన్ని మరింత సరిగ్గా ప్రతిబింబిస్తుంది. అంటే, ఇది క్యూ కంటే ఎక్కువ సెట్. థ్రెడ్ main
టాస్క్ ఆబ్జెక్ట్తో కొత్త థ్రెడ్ను సృష్టిస్తుంది, దాన్ని ప్రారంభించి, 3 సెకన్లు వేచి ఉంటుంది. ఇది కొత్త థ్రెడ్ థ్రెడ్కు ముందు లాక్ని పొందగలిగేలా చేస్తుంది main
మరియు మానిటర్ క్యూలోకి వచ్చే అవకాశం ఉంది. ఆ తర్వాత, main
థ్రెడ్ స్వయంగా ఆబ్జెక్ట్ యొక్క సమకాలీకరించబడిన బ్లాక్లోకి ప్రవేశిస్తుంది lock
మరియు మానిటర్ని ఉపయోగించి థ్రెడ్ నోటిఫికేషన్ను నిర్వహిస్తుంది. నోటిఫికేషన్ పంపిన తర్వాత, main
థ్రెడ్ విడుదల చేస్తుందిlock
ఆబ్జెక్ట్ యొక్క మానిటర్ మరియు కొత్త థ్రెడ్, lock
ఆబ్జెక్ట్ యొక్క మానిటర్ విడుదల కోసం మునుపు వేచి ఉంది, ఇది అమలును కొనసాగిస్తుంది. notify()
కేవలం ఒక థ్రెడ్ ( )కి లేదా క్యూలోని అన్ని థ్రెడ్లకు ఏకకాలంలో ( ) నోటిఫికేషన్ను పంపడం సాధ్యమవుతుంది notifyAll()
. ఇక్కడ మరింత చదవండి: Javaలో notify() మరియు notifyAll() మధ్య వ్యత్యాసం . JVM ఎలా అమలు చేయబడుతుందనే దానిపై నోటిఫికేషన్ ఆర్డర్ ఆధారపడి ఉంటుందని గమనించడం ముఖ్యం. ఇక్కడ మరింత చదవండి: అందరికీ తెలియజేయడం మరియు తెలియజేయడం ద్వారా ఆకలిని ఎలా పరిష్కరించాలి? . ఒక వస్తువును పేర్కొనకుండానే సమకాలీకరణను నిర్వహించవచ్చు. ఒకే బ్లాక్ కోడ్ కాకుండా మొత్తం పద్ధతి సమకాలీకరించబడినప్పుడు మీరు దీన్ని చేయవచ్చు. ఉదాహరణకు, స్టాటిక్ పద్ధతుల కోసం, లాక్ క్లాస్ ఆబ్జెక్ట్ అవుతుంది (ద్వారా పొందబడింది .class
):
public static synchronized void printA() {
System.out.println("A");
}
public static void printB() {
synchronized(HelloWorld.class) {
System.out.println("B");
}
}
తాళాలను ఉపయోగించడం పరంగా, రెండు పద్ధతులు ఒకే విధంగా ఉంటాయి. ఒక పద్ధతి స్థిరంగా లేకుంటే, కరెంట్ని ఉపయోగించి సమకాలీకరణ నిర్వహించబడుతుంది instance
, అంటే this
. మార్గం ద్వారా, getState()
థ్రెడ్ యొక్క స్థితిని పొందడానికి మీరు పద్ధతిని ఉపయోగించవచ్చని మేము ఇంతకు ముందే చెప్పాము. wait()
ఉదాహరణకు, మానిటర్ కోసం వేచి ఉన్న క్యూలో ఉన్న థ్రెడ్ కోసం, పద్ధతి గడువు ముగిసిందని పేర్కొన్నట్లయితే , స్థితి వేచి ఉంటుంది లేదా TIMED_WAITINGగా ఉంటుంది .
https://stackoverflow.com/questions/36425942/what-is-the-lifecycle-of-thread-in-java
థ్రెడ్ జీవిత చక్రం
దాని జీవిత కాలంలో, థ్రెడ్ యొక్క స్థితి మారుతుంది. వాస్తవానికి, ఈ మార్పులు థ్రెడ్ యొక్క జీవిత చక్రాన్ని కలిగి ఉంటాయి. థ్రెడ్ సృష్టించబడిన వెంటనే, దాని స్థితి కొత్తది. ఈ స్థితిలో, కొత్త థ్రెడ్ ఇంకా అమలులో లేదు మరియు జావా థ్రెడ్ షెడ్యూలర్కి దాని గురించి ఇంకా ఏమీ తెలియదు. థ్రెడ్ షెడ్యూలర్ థ్రెడ్ గురించి తెలుసుకోవడానికి, మీరు తప్పనిసరిగాthread.start()
పద్ధతికి కాల్ చేయాలి. అప్పుడు థ్రెడ్ RUNNABLE స్థితికి మారుతుంది. ఇంటర్నెట్లో చాలా సరికాని రేఖాచిత్రాలు ఉన్నాయి, ఇవి "రన్ చేయదగిన" మరియు "రన్నింగ్" స్థితులను వేరు చేస్తాయి. కానీ ఇది పొరపాటు, ఎందుకంటే జావా "పని చేయడానికి సిద్ధంగా ఉంది" (రన్ చేయదగినది) మరియు "పని చేయడం" (రన్నింగ్) మధ్య తేడాను గుర్తించదు. థ్రెడ్ సజీవంగా ఉన్నప్పటికీ సక్రియంగా లేనప్పుడు (రన్ చేయదగినది కాదు), అది రెండు రాష్ట్రాల్లో ఒకదానిలో ఉంటుంది:
- నిరోధించబడింది — క్లిష్టమైన విభాగంలో ప్రవేశించడానికి వేచి ఉంది, అనగా ఒక
synchronized
బ్లాక్. - వేచి ఉండటం — కొంత షరతును తీర్చడానికి మరొక థ్రెడ్ కోసం వేచి ఉంది.
getState()
పద్ధతిని ఉపయోగించండి. థ్రెడ్లు కూడా ఒక isAlive()
పద్ధతిని కలిగి ఉంటాయి, థ్రెడ్ని ముగించకపోతే అది నిజం అని చూపుతుంది.
లాక్ సపోర్ట్ మరియు థ్రెడ్ పార్కింగ్
జావా 1.6తో ప్రారంభించి, లాక్సపోర్ట్ అనే ఆసక్తికరమైన మెకానిజం కనిపించింది.
park()
వెంటనే తిరిగి వస్తుంది, ప్రక్రియలో అనుమతిని వినియోగిస్తుంది. లేకపోతే, అది అడ్డుకుంటుంది. పద్ధతికి కాల్ చేయడం వలన unpark
అనుమతి ఇంకా అందుబాటులో లేకుంటే అది అందుబాటులో ఉంటుంది. 1 అనుమతి మాత్రమే ఉంది. జావా డాక్యుమెంటేషన్ LockSupport
తరగతిని సూచిస్తుంది Semaphore
. ఒక సాధారణ ఉదాహరణ చూద్దాం:
import java.util.concurrent.Semaphore;
public class HelloWorldApp{
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(0);
try {
semaphore.acquire();
} catch (InterruptedException e) {
// Request the permit and wait until we get it
e.printStackTrace();
}
System.out.println("Hello, World!");
}
}
ఈ కోడ్ ఎల్లప్పుడూ వేచి ఉంటుంది, ఎందుకంటే ఇప్పుడు సెమాఫోర్కు 0 అనుమతులు ఉన్నాయి. మరియు acquire()
కోడ్లో పిలిచినప్పుడు (అంటే అనుమతిని అభ్యర్థించండి), థ్రెడ్ అనుమతి పొందే వరకు వేచి ఉంటుంది. మేము వేచి ఉన్నందున, మనం నిర్వహించాలి InterruptedException
. ఆసక్తికరంగా, సెమాఫోర్ ప్రత్యేక థ్రెడ్ స్థితిని పొందుతుంది. మనం JVisualVMలో చూస్తే, రాష్ట్రం "వెయిట్" కాదు, "పార్క్" అని మనకు కనిపిస్తుంది. 
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
// Park the current thread
System.err.println("Will be Parked");
LockSupport.park();
// As soon as we are unparked, we will start to act
System.err.println("Unparked");
};
Thread th = new Thread(task);
th.start();
Thread.currentThread().sleep(2000);
System.err.println("Thread state: " + th.getState());
LockSupport.unpark(th);
Thread.currentThread().sleep(2000);
}
థ్రెడ్ యొక్క స్థితి వేచి ఉంటుంది, కానీ JVisualVM కీవర్డ్ wait
నుండి synchronized
మరియు తరగతి park
నుండి వేరు చేస్తుంది LockSupport
. ఇది ఎందుకు LockSupport
చాలా ముఖ్యమైనది? మేము మళ్లీ జావా డాక్యుమెంటేషన్కి వెళ్లి, వేచి ఉన్న థ్రెడ్ స్థితిని చూస్తాము . మీరు గమనిస్తే, దానిలోకి ప్రవేశించడానికి మూడు మార్గాలు మాత్రమే ఉన్నాయి. వాటిలో రెండు మార్గాలు wait()
మరియు join()
. మరియు మూడవది LockSupport
. జావాలో, తాళాలు కూడా tలో నిర్మించబడతాయి LockSuppor
మరియు ఉన్నత-స్థాయి సాధనాలను అందిస్తాయి. ఒకదాన్ని ఉపయోగించడానికి ప్రయత్నిద్దాం. ఉదాహరణకు, పరిశీలించండి ReentrantLock
:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class HelloWorld{
public static void main(String []args) throws InterruptedException {
Lock lock = new ReentrantLock();
Runnable task = () -> {
lock.lock();
System.out.println("Thread");
lock.unlock();
};
lock.lock();
Thread th = new Thread(task);
th.start();
System.out.println("main");
Thread.currentThread().sleep(2000);
lock.unlock();
}
}
మునుపటి ఉదాహరణలలో వలె, ఇక్కడ ప్రతిదీ సులభం. lock
భాగస్వామ్య వనరును ఎవరైనా విడుదల చేయడానికి ఆబ్జెక్ట్ వేచి ఉంది . main
మేము JVisualVMలో చూస్తే, థ్రెడ్ లాక్ని విడుదల చేసే వరకు కొత్త థ్రెడ్ పార్క్ చేయబడుతుందని మేము చూస్తాము . మీరు ఇక్కడ లాక్ల గురించి మరింత చదవవచ్చు: Java 8 StampedLocks vs. ReadWriteLocks మరియు Synchronized మరియు Javaలో లాక్ API. లాక్లు ఎలా అమలు చేయబడతాయో బాగా అర్థం చేసుకోవడానికి, ఈ కథనంలో ఫేజర్ గురించి చదవడం సహాయకరంగా ఉంటుంది: జావా ఫేజర్కి గైడ్ . మరియు వివిధ సింక్రోనైజర్ల గురించి మాట్లాడుతూ, మీరు జావా సింక్రొనైజర్లపై DZone కథనాన్ని తప్పక చదవాలి.
ముగింపు
ఈ సమీక్షలో, జావాలో థ్రెడ్లు పరస్పర చర్య చేసే ప్రధాన మార్గాలను మేము పరిశీలించాము. అదనపు పదార్థం:- కలిసి ఉత్తమం: జావా మరియు థ్రెడ్ క్లాస్. పార్ట్ I - అమలు యొక్క థ్రెడ్స్
- https://dzone.com/articles/the-java-synchronizers
- https://www.javatpoint.com/java-multithreading-interview-questions
GO TO FULL VERSION