JavaRush /Java Blog /Random-TL /Hindi Mo Masisira ang Java gamit ang isang Thread: Bahagi...

Hindi Mo Masisira ang Java gamit ang isang Thread: Bahagi I - Mga Thread

Nai-publish sa grupo

Panimula

Ang multithreading ay itinayo sa Java mula noong mga unang araw nito. Kaya't tingnan natin kung tungkol saan ang multithreading. Hindi mo masisira ang Java gamit ang isang Thread: Part I - Threads - 1Kunin natin ang opisyal na aral mula sa Oracle bilang panimulang punto: " Lesson: The "Hello World!" Application ". Baguhin natin ng kaunti ang code ng ating Hello World application sa sumusunod:
class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello, " + args[0]);
    }
}
argsay isang hanay ng mga parameter ng input na ipinasa kapag nagsimula ang programa. I-save natin ang code na ito sa isang file na may pangalan na tumutugma sa pangalan ng klase at extension .java. Mag-compile tayo gamit ang javac utility : javac HelloWorldApp.java Pagkatapos nito, tawagan ang aming code na may ilang parameter, halimbawa, Roger: java HelloWorldApp Roger Hindi mo masisira ang Java gamit ang isang Thread: Bahagi I - Mga Thread - 2Ang aming code ay mayroon na ngayong malubhang depekto. Kung hindi kami magpasa ng anumang argumento (i.e. i-execute lang ang java HelloWorldApp), magkakaroon kami ng error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
        at HelloWorldApp.main(HelloWorldApp.java:3)
Isang pagbubukod (ibig sabihin, isang error) ang naganap sa isang thread na pinangalanang main. Ito ay lumiliko na mayroong ilang mga uri ng mga thread sa Java? Dito na magsisimula ang ating paglalakbay.

Java at mga thread

Upang maunawaan kung ano ang isang thread, kailangan mong maunawaan kung paano inilunsad ang isang Java application. Baguhin natin ang ating code gaya ng sumusunod:
class HelloWorldApp {
    public static void main(String[] args) {
		while (true) {
			//Do nothing
		}
	}
}
Ngayon ay i-compile natin ito muli gamit ang javac. Susunod, para sa kaginhawahan, patakbuhin namin ang aming Java code sa isang hiwalay na window. Sa Windows maaari mong gawin ito tulad nito: start java HelloWorldApp. Ngayon, gamit ang jps utility , tingnan natin kung anong impormasyon ang sasabihin sa atin ng Java: Hindi mo masisira ang Java gamit ang isang Thread: Bahagi I - Mga Thread - 3Ang unang numero ay ang PID o Process ID, ang process identifier. Ano ang isang proseso?
Процесс — это совокупность codeа и данных, разделяющих общее виртуальное addressное пространство.
Sa tulong ng mga proseso, ang pagpapatupad ng iba't ibang mga programa ay nakahiwalay sa bawat isa: ang bawat aplikasyon ay gumagamit ng sarili nitong lugar ng memorya nang hindi nakakasagabal sa iba pang mga programa. Ipinapayo ko sa iyo na basahin ang artikulo nang mas detalyado: " https://habr.com/post/164487/ ". Ang isang proseso ay hindi maaaring umiral nang walang mga thread, kaya kung mayroong isang proseso, hindi bababa sa isang thread ang umiiral dito. Paano ito nangyayari sa Java? Kapag nagpatakbo kami ng isang Java program, ang pagpapatupad nito ay magsisimula sa main. Uri ng pagpasok namin sa programa, kaya ang espesyal na paraan na ito mainay tinatawag na entry point, o "entry point". Ang pamamaraan mainay dapat palaging public static voidupang ang Java Virtual Machine (JVM) ay makapagsimulang isagawa ang aming programa. Tingnan ang " Bakit static ang pangunahing pamamaraan ng Java? " para sa higit pang mga detalye. Lumalabas na ang java launcher (java.exe o javaw.exe) ay isang simpleng application (simpleng C application): naglo-load ito ng iba't ibang DLL, na talagang JVM. Ang Java launcher ay gumagawa ng isang partikular na hanay ng mga Java Native Interface (JNI) na tawag. Ang JNI ay ang mekanismo na nagtulay sa mundo ng Java Virtual Machine at sa mundo ng C++. Lumalabas na ang launcher ay hindi ang JVM, ngunit ang loader nito. Alam nito ang tamang mga utos na isasagawa upang simulan ang JVM. Alam kung paano ayusin ang lahat ng kinakailangang kapaligiran gamit ang mga tawag sa JNI. Kasama rin sa organisasyong ito ng kapaligiran ang paglikha ng isang pangunahing thread, na karaniwang tinatawag na main. Upang mas malinaw na makita kung anong mga thread ang nakatira sa isang proseso ng java, ginagamit namin ang jvisualvm program , na kasama sa JDK. Alam ang pid ng isang proseso, maaari naming buksan kaagad ang data dito: jvisualvm --openpid айдипроцесса Hindi mo masisira ang Java gamit ang isang Thread: Bahagi I - Mga Thread - 4Kapansin-pansin, ang bawat thread ay may sariling hiwalay na lugar sa memorya na inilaan para sa proseso. Ang istraktura ng memorya na ito ay tinatawag na stack. Ang isang stack ay binubuo ng mga frame. Ang isang frame ay ang punto ng pagtawag ng isang pamamaraan, punto ng pagpapatupad. Ang isang frame ay maaari ding katawanin bilang isang StackTraceElement (tingnan ang Java API para sa StackTraceElement ). Maaari kang magbasa nang higit pa tungkol sa memorya na inilaan sa bawat thread dito . Kung titingnan natin ang Java API at hahanapin ang salitang Thread, makikita natin na mayroong class na java.lang.Thread . Ang klase na ito ang kumakatawan sa isang stream sa Java, at kasama nito kailangan nating magtrabaho. Thread'ом Java не испортишь: Часть I — потоки - 5

java.lang.Thread

Ang isang thread sa Java ay kinakatawan bilang isang halimbawa ng klase java.lang.Thread. Ito ay nagkakahalaga ng pag-unawa kaagad na ang mga pagkakataon ng klase ng Thread sa Java ay hindi mga thread mismo. Isa lang itong uri ng API para sa mga low-level na thread na pinamamahalaan ng JVM at ng operating system. Kapag inilunsad namin ang JVM gamit ang java launcher, lumilikha ito ng pangunahing thread na may pangalan mainat marami pang mga thread ng serbisyo. Gaya ng nakasaad sa JavaDoc ng klase ng Thread: When a Java Virtual Machine starts up, there is usually a single non-daemon thread Mayroong 2 uri ng mga thread: mga daemon at hindi mga daemon. Ang mga daemon thread ay mga background thread (mga service thread) na gumaganap ng ilang trabaho sa background. Ang kawili-wiling terminong ito ay isang sanggunian sa "demonyo ni Maxwell," na maaari mong basahin nang higit pa tungkol sa artikulo sa Wikipedia tungkol sa " mga demonyo ." Gaya ng nakasaad sa dokumentasyon, patuloy na isinasagawa ng JVM ang programa (proseso) hanggang:
  • Ang Runtime.exit na paraan ay hindi tinatawag
  • Nakumpleto ng lahat ng mga thread na hindi daemon ang kanilang trabaho (parehong walang mga error at may mga pagbubukod na itinapon)
Kaya ang mahalagang detalye: ang mga daemon thread ay maaaring wakasan sa anumang utos na ipapatupad. Samakatuwid, ang integridad ng data sa kanila ay hindi ginagarantiyahan. Samakatuwid, ang mga daemon thread ay angkop para sa ilang mga gawain sa serbisyo. Halimbawa, sa Java mayroong isang thread na responsable para sa pagproseso ng mga pamamaraan ng pag-finalize o mga thread na nauugnay sa Garbage Collector (GC). Ang bawat thread ay kabilang sa ilang grupo ( ThreadGroup ). At ang mga grupo ay maaaring pumasok sa isa't isa, na bumubuo ng ilang hierarchy o istraktura.
public static void main(String []args){
	Thread currentThread = Thread.currentThread();
	ThreadGroup threadGroup = currentThread.getThreadGroup();
	System.out.println("Thread: " + currentThread.getName());
	System.out.println("Thread Group: " + threadGroup.getName());
	System.out.println("Parent Group: " + threadGroup.getParent().getName());
}
Binibigyang-daan ka ng mga grupo na i-streamline ang pamamahala ng mga daloy at subaybayan ang mga ito. Bilang karagdagan sa mga grupo, ang mga thread ay may sariling exception handler. Tingnan natin ang isang halimbawa:
public static void main(String []args) {
	Thread th = Thread.currentThread();
	th.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
		@Override
		public void uncaughtException(Thread t, Throwable e) {
			System.out.println("An error occurred: " + e.getMessage());
		}
	});
    System.out.println(2/0);
}
Ang paghahati ng zero ay magdudulot ng error na mahuhuli ng handler. Kung hindi mo mismo tinukoy ang handler, gagana ang default na pagpapatupad ng handler, na magpapakita ng error stack sa StdError. Maaari kang magbasa nang higit pa sa pagsusuri http://pro-java.ru/java-dlya-opytnyx/obrabotchik-neperexvachennyx-isklyuchenij-java/ ". Bilang karagdagan, ang thread ay may priyoridad. Maaari kang magbasa nang higit pa tungkol sa mga priyoridad sa artikulong " Java Thread Priority sa Multithreading ".

Paggawa ng thread

Gaya ng nakasaad sa dokumentasyon, mayroon kaming 2 paraan para gumawa ng thread. Ang una ay lumikha ng iyong sariling tagapagmana. Halimbawa:
public class HelloWorld{
    public static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("Hello, World!");
        }
    }

    public static void main(String []args){
        Thread thread = new MyThread();
        thread.start();
    }
}
Tulad ng nakikita mo, ang gawain ay inilunsad sa pamamaraan run, at ang thread ay inilunsad sa pamamaraan start. Hindi sila dapat malito, dahil... kung tatakbo tayo nang direkta sa pamamaraan run, walang bagong thread na magsisimula. Ito ang paraan startna humihiling sa JVM na lumikha ng bagong thread. Ang opsyon na may descendant mula sa Thread ay masama dahil isinama namin ang Thread sa hierarchy ng klase. Ang pangalawang kawalan ay nagsisimula na tayong lumabag sa prinsipyo ng "Sole Responsibility" SOLID, dahil ang aming klase ay nagiging sabay-sabay na responsable para sa parehong pamamahala sa thread at para sa ilang gawain na dapat gawin sa thread na ito. Ano ang tama? Ang sagot ay nasa mismong pamamaraan runna aming na-override:
public void run() {
	if (target != null) {
		target.run();
	}
}
Narito targetang ilang java.lang.Runnable, na maaari naming ipasa sa Thread kapag gumagawa ng isang instance ng klase. Samakatuwid, magagawa natin ito:
public class HelloWorld{
    public static void main(String []args){
        Runnable task = new Runnable() {
            public void run() {
                System.out.println("Hello, World!");
            }
        };
        Thread thread = new Thread(task);
        thread.start();
    }
}
Isa rin itong Runnablefunctional na interface mula noong Java 1.8. Nagbibigay-daan ito sa iyo na magsulat ng task code para sa mga thread nang mas maganda:
public static void main(String []args){
	Runnable task = () -> {
		System.out.println("Hello, World!");
	};
	Thread thread = new Thread(task);
	thread.start();
}

Kabuuan

Kaya, umaasa ako mula sa kuwentong ito ay malinaw kung ano ang isang stream, kung paano sila umiiral at kung anong mga pangunahing operasyon ang maaaring gawin sa kanila. Sa susunod na bahagi , sulit na maunawaan kung paano nakikipag-ugnayan ang mga thread sa isa't isa at kung ano ang kanilang ikot ng buhay. #Viacheslav
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION