CodeGym/Java Blog/Random/Mas mahusay na magkasama: Java at ang klase ng Thread. Ba...
John Squirrels
Antas
San Francisco

Mas mahusay na magkasama: Java at ang klase ng Thread. Bahagi I - Mga Thread ng pagpapatupad

Nai-publish sa grupo

Panimula

Ang multithreading ay binuo sa Java mula pa sa simula. Kaya, tingnan natin sandali ang bagay na ito na tinatawag na multithreading. Mas mahusay na magkasama: Java at ang klase ng Thread.  Bahagi I — Mga Thread ng pagpapatupad - 1Kinukuha namin ang opisyal na aralin mula sa Oracle bilang reference point: " Lesson: The "Hello World!" Application ". Bahagyang babaguhin namin ang code ng aming programang Hello World gaya ng 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 ang code na ito sa isang file na may pangalan na tumutugma sa pangalan ng klase at may extension na .java. I-compile ito gamit ang javac utility: javac HelloWorldApp.java. Pagkatapos, pinapatakbo namin ang aming code gamit ang ilang parameter, halimbawa, "Roger": java HelloWorldApp Roger Mas mahusay na magkasama: Java at ang klase ng Thread.  Bahagi I — Mga Thread ng pagpapatupad - 2Ang aming code ay kasalukuyang may malubhang depekto. Kung hindi ka pumasa sa anumang argumento (ibig sabihin, 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 thread na pinangalanang "pangunahing". Kaya, may mga thread ang Java? Dito na magsisimula ang ating paglalakbay.

Java at mga thread

Upang maunawaan kung ano ang isang thread, kailangan mong maunawaan kung paano nagsisimula ang isang Java program. 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 itong muli gamit ang javac. Para sa kaginhawahan, patakbuhin namin ang aming Java code sa isang hiwalay na window. Sa Windows, ito ay maaaring gawin tulad nito: start java HelloWorldApp. Ngayon ay gagamitin namin ang jps utility upang makita kung anong impormasyon ang maaaring sabihin sa amin ng Java: Mas mahusay na magkasama: Java at ang klase ng Thread.  Bahagi I — Mga Thread ng pagpapatupad - 3Ang unang numero ay ang PID o Process ID. Ano ang isang proseso?
A process is a combination of code and data sharing a common virtual address space.
Sa mga proseso, ang iba't ibang mga programa ay nakahiwalay sa isa't isa habang tumatakbo ang mga ito: ang bawat application ay gumagamit ng sarili nitong lugar sa memorya nang hindi nakakasagabal sa ibang mga programa. Upang matuto nang higit pa, inirerekomenda kong basahin ang tutorial na ito: Mga Proseso at Mga Thread . Hindi maaaring umiral ang isang proseso nang walang thread, kaya kung may proseso, mayroon itong kahit isang thread. Ngunit paano ito nangyayari sa Java? Kapag nagsimula kami ng isang Java program, magsisimula ang pagpapatupad sa mainpamamaraan. Para tayong tumuntong sa programa, kaya ang espesyal mainna pamamaraang ito ay tinatawag na entry point. Ang mainpamamaraan ay dapat palaging "public static void", upang ang Java virtual machine (JVM) ay makapagsimulang isagawa ang aming programa. Para sa karagdagang impormasyon, Bakit static ang pangunahing pamamaraan ng Java?. Lumalabas na ang Java launcher (java.exe o javaw.exe) ay isang simpleng C application: nilo-load nito ang iba't ibang DLL na talagang binubuo ng JVM. Ang Java launcher ay gumagawa ng isang partikular na hanay ng mga Java Native Interface (JNI) na tawag. Ang JNI ay isang mekanismo para sa pagkonekta sa mundo ng Java virtual machine sa mundo ng C++. Kaya, ang launcher ay hindi ang JVM mismo, ngunit isang mekanismo para i-load ito. Alam nito ang mga tamang utos na ipapatupad para masimulan ang JVM. Alam nito kung paano gamitin ang mga tawag sa JNI para i-set up ang kinakailangang kapaligiran. Kasama sa pag-set up ng environment na ito ang paglikha ng pangunahing thread, na tinatawag na "pangunahing", siyempre. Upang mas mahusay na mailarawan kung aling mga thread ang umiiral sa isang proseso ng Java, ginagamit namin ang jvisualvmtool, na kasama sa JDK. Alam ang pid ng isang proseso, makikita natin kaagad ang impormasyon tungkol sa prosesong iyon: jvisualvm --openpid <process id> Mas mahusay na magkasama: Java at ang klase ng Thread.  Bahagi I — Mga Thread ng pagpapatupad - 4Kapansin-pansin, ang bawat thread ay may sariling hiwalay na lugar sa memorya na inilalaan sa proseso. Ang istraktura ng memorya na ito ay tinatawag na stack. Ang isang stack ay binubuo ng mga frame. Ang isang frame ay kumakatawan sa pag-activate ng isang pamamaraan (isang hindi natapos na tawag sa pamamaraan). Ang isang frame ay maaari ding katawanin bilang isang StackTraceElement (tingnan ang Java API para sa StackTraceElement ). Makakahanap ka ng higit pang impormasyon tungkol sa memorya na inilalaan sa bawat thread sa talakayan dito: " Paano naglalaan ang Java (JVM) ng stack para sa bawat thread ". Kung titingnan mo ang Java API at hahanapin ang salitang "Thread", makikita mo ang java.lang.Threadklase. Ito ang klase na kumakatawan sa isang thread sa Java, at kakailanganin nating magtrabaho dito. Mas mahusay na magkasama: Java at ang klase ng Thread.  Bahagi I — Mga Thread ng pagpapatupad - 5

java.lang.Thread

Sa Java, ang isang thread ay kinakatawan ng isang halimbawa ng java.lang.Threadklase. Dapat mong maunawaan kaagad na ang mga pagkakataon ng klase ng Thread ay hindi mismo mga thread ng pagpapatupad. Isa lang itong uri ng API para sa mga low-level na thread na pinamamahalaan ng JVM at ng operating system. Kapag sinimulan natin ang JVM gamit ang Java launcher, lumilikha ito ng mainthread na tinatawag na "pangunahing" at ilang iba pang mga housekeeping thread. Gaya ng nakasaad sa JavaDoc para sa 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 thread ng Daemon ay mga thread sa background (housekeeping) na gumagawa ng ilang trabaho sa background. Ang salitang "daemon" ay tumutukoy sa demonyo ni Maxwell. Maaari kang matuto nang higit pa sa artikulong ito sa Wikipedia . Gaya ng nakasaad sa dokumentasyon, patuloy na isinasagawa ng JVM ang programa (proseso) hanggang:
  • Tinatawag ang Runtime.exit() na pamamaraan
  • Ang lahat ng NON-daemon thread ay tinatapos ang kanilang trabaho (nang walang mga error o may mga itinapon na mga pagbubukod)
Ang isang mahalagang detalye ay sumusunod mula dito: ang mga thread ng daemon ay maaaring wakasan sa anumang punto. Bilang resulta, walang mga garantiya tungkol sa integridad ng kanilang data. Alinsunod dito, ang mga thread ng daemon ay angkop para sa ilang mga gawain sa housekeeping. Halimbawa, ang Java ay may isang thread na responsable para sa pagpoproseso ng finalize()mga tawag sa pamamaraan, ibig sabihin, mga thread na kasangkot sa Garbage Collector (gc). Ang bawat thread ay bahagi ng isang grupo ( ThreadGroup ). At ang mga grupo ay maaaring maging bahagi ng iba pang mga grupo, na bumubuo ng isang tiyak na 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());
}
Ang mga grupo ay nagdadala ng kaayusan sa pamamahala ng thread. Bilang karagdagan sa mga grupo, ang mga thread ay may sariling exception handler. Tingnan 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 tutukuyin ang sarili mong handler, ang JVM ay tatawagin ang default na handler, na maglalabas ng stack trace ng exception sa StdError. May priority din ang bawat thread. Maaari kang magbasa ng higit pa tungkol sa mga priyoridad sa artikulong ito: Java Thread Priority sa Multithreading .

Paggawa ng thread

Gaya ng nakasaad sa dokumentasyon, mayroon kaming 2 paraan para gumawa ng thread. Ang unang paraan ay ang lumikha ng iyong sariling subclass. 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 ng gawain ay nangyayari sa run()pamamaraan, ngunit ang thread mismo ay nagsimula sa start()pamamaraan. Huwag malito ang mga pamamaraang ito: kung tatawagin natin un()nang direkta ang r method, walang bagong thread ang magsisimula. Ito ang start()paraan na humihiling sa JVM na lumikha ng bagong thread. Ang opsyong ito kung saan namin inherit ang Thread ay masama na dahil isinama namin ang Thread sa aming class hierarchy. Ang pangalawang disbentaha ay nagsisimula na tayong lumabag sa prinsipyong "nag-iisang responsibilidad". Iyon ay, ang aming klase ay sabay-sabay na responsable para sa pagkontrol sa thread at para sa ilang gawain na isasagawa sa thread na ito. Ano ang tamang paraan? Ang sagot ay matatagpuan sa parehong run()paraan, na aming na-override:
public void run() {
	if (target != null) {
		target.run();
	}
}
Narito, targetang ilan java.lang.Runnable, na maaari nating ipasa kapag lumilikha ng isang halimbawa ng klase ng Thread. Nangangahulugan ito na 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();
    }
}
Runnableay isa ring functional na interface mula noong Java 1.8. Ginagawa nitong posible na magsulat ng mas magandang code para sa gawain ng isang thread:
public static void main(String[] args) {
	Runnable task = () -> {
		System.out.println("Hello, World!");
	};
	Thread thread = new Thread(task);
	thread.start();
}

Konklusyon

Sana ay linawin ng talakayang ito kung ano ang isang thread, kung paano umiral ang mga thread, at kung anong mga pangunahing operasyon ang maaaring gawin sa mga thread. Sa susunod na bahagi , susubukan naming maunawaan kung paano nakikipag-ugnayan ang mga thread sa isa't isa at tuklasin ang ikot ng buhay ng thread. Mas mahusay na magkasama: Java at ang klase ng Thread. Bahagi II — Pag-synchronize Mas mahusay na magkasama: Java at ang Thread na klase. Part III — Mas Mahusay na Pakikipag-ugnayan: Java at ang Thread class. Bahagi IV — Matatawagan, Hinaharap, at mga kaibigan Mas mahusay na magkasama: Java at ang Thread na klase. Part V — Executor, ThreadPool, Fork/Join Better together: Java at ang Thread class. Bahagi VI - Sunog!
Mga komento
  • Sikat
  • Bago
  • Luma
Dapat kang naka-sign in upang mag-iwan ng komento
Wala pang komento ang page na ito