멀티 스레딩은 Java에서 매우 중요한 지식 지점입니다. 여기에서 편집기는 Java Thread Multithreading을 요약하여 매우 유용합니다. 나는 당신이 그것을 마스터 할 수 있기를 바랍니다.
1. 실의 수명주기와 5 개의 기본 상태
Java의 실의 수명주기와 관련하여 먼저 다음 고전적인 그림을 살펴 보겠습니다.
위의 그림은 기본적으로 자바에서 멀티 스레딩의 중요한 지식 지점을 다룹니다. 위 그림에서 지식 지점을 마스터하면 기본적으로 자바에서 멀티 스레딩을 마스터하게됩니다. 주로 포함 :
Java 스레드에는 5 개의 기본 상태가 있습니다
새 상태 (New) : 스레드 객체 쌍이 만들어지면 다음과 같은 새 상태가 들어갑니다. 스레드 t = new Mythread ();
준비 상태 (runnable) : 스레드 개체 (t.start ();)의 start () 메소드가 있으면 스레드가 준비 상태로 들어갑니다. 준비 상태의 스레드는 스레드가 준비되었고 CPU가 언제든지 실행을 일정하기를 기다리고 있음을 의미합니다.
실행 상태 : CPU가 준비 상태에서 스레드를 예약하기 시작하면 스레드를 진정으로 실행할 수 있습니다. 즉, 실행 상태로 들어갑니다. 참고 : 준비 상태는 실행중인 상태에 대한 유일한 항목입니다. 즉, 스레드가 실행 상태에 입력하려면 먼저 준비 상태에 있어야합니다.
차단 상태 : 어떤 이유로 든 실행 상태의 스레드는 일시적으로 CPU 사용을 포기하고 실행을 중지합니다. 현재 블로킹 상태로 들어갑니다. CPU가 다시 실행중인 상태에 들어가기 위해 다시 전화 할 기회가 없습니다.
차단 이유에 따라 차단 상태를 세 가지 유형으로 나눌 수 있습니다.
1. 차단 대기 : 실행중인 상태의 스레드는 대기 상태를 차단 상태로 입력하기 위해 대기 () 메소드를 실행합니다.
2. 동기화 된 차단- 스레드는 동기화 된 동기화 잠금을 얻지 못하며 (잠금이 다른 스레드에 의해 점유되어 있기 때문에) 동기화 된 차단 상태로 들어갑니다.
3. 기타 차단-스레드의 sleep () 또는 join ()을 호출하거나 I/O 요청을 발행하여 스레드가 차단 상태로 들어갑니다. Sleep () State가 시간이 초과되면 join ()는 스레드가 끝나거나 시간이 끝나기를 기다렸거나 I/O 처리가 완료되면 스레드가 준비 상태에 다시 들어갔습니다.
DEAD : 스레드는 예외로 인해 실행 () 메소드를 실행하거나 종료했으며 스레드는 수명주기를 종료합니다.
2. Java Multithreads의 생성 및 시작
Java에는 스레드 생성의 세 가지 기본 형태가 있습니다.
1. 스레드 클래스를 상속하고 클래스의 run () 메소드를 무시합니다.
클래스 Mythread는 스레드 {private int i =; @overridepublic void run () {for (i =; i <; i ++) {system.out.println (thread.currentthread (). getName ()+""+i);}} public strood void main (string) {in i = in i =; int} {in}} {in}}}}; {system.out.println (thread.currentthread (). getName () + "" + i); if (i ==) {Thread Mythread = new Mythread (); // 새 스레드 생성 신화이 스레드는 새 상태에 들어갑니다. // 새 스레드 생성 Mythread이 스레드는 새 상태 Mythread.start ()에 들어갑니다. // START () 메서드를 호출하여 스레드가 준비 상태를 입력하게합니다. state mythread.start (); // START () 메서드를 호출하여 스레드가 준비 상태를 입력하게합니다}}}} 위에서 볼 수 있듯이 스레드 클래스를 상속하고 run () 메소드를 무시하고, 새로운 스레드 클래스 신화가 정의되며, 여기서 run () 메소드의 메소드 본문은 스레드가 완료 해야하는 작업을 나타내고 스레드 실행 본체라고합니다. 이 스레드 클래스 객체를 만들 때 새 스레드가 생성되어 새 스레드 상태로 들어갑니다. 스레드 객체에서 참조 된 start () 메소드를 호출하면 스레드가 준비 상태로 들어갑니다. 현재 CPU 스케줄링 타이밍에 따라 스레드가 즉시 실행되지 않을 수 있습니다.
2. runnable 인터페이스를 구현하고 인터페이스의 run () 메소드를 재정의합니다. run () 메소드는 또한 스레드 실행 본체이며, runnable 구현 클래스의 인스턴스를 작성 하고이 인스턴스를 스레드 클래스의 대상으로 사용하여 스레드 개체를 만듭니다. 스레드 객체는 실제 스레드 객체입니다.
클래스 myrunnable empless runnable {private int i =; @overridepublic void run () {for (i =; i <; i ++) {system.out.println (thread.currentThread (). getName ()} public strood void main (string []) {i = (int i =); {system.out.println (thread.currentthread (). getName () + "" + i); if (i ==) {runnable myrunnable = new myrunnable (); // 실행 가능한 구현 객체를 만듭니다. 클래스 스레드 스레드 = 새 스레드 (myrunnable); // myrunnable을 스레드 대상으로 사용하여 새 스레드 스레드를 생성합니다. 스레드 스레드 = 새 스레드 (myrunnable); thread.start (); // strest () 메서드를 호출하여 스레드가 준비 상태 스레드를 입력하도록합니다 .Strart.Start ();}}}} 나는 모든 사람이 새로운 스레드를 만드는 위의 두 가지 방법에 익숙하다고 생각합니다. 그렇다면 스레드와 달리기 가능한 관계는 무엇입니까? 먼저 다음 예를 살펴 보겠습니다.
공개 클래스 스레드 테스트 {public static void main (string [] args) {for (int i =; i <; i ++) {system.out.println (thread.currentthread (). getName () + "" + i); if (i ==) {runnable myRunnable = new Myrunnable (); mythread (myrunnable); ride.start ();}}}} 클래스 myrunnable empless runnable {private int i =; @overridepublic void run () {system.out.println ( "myrunnable run"); for (i =; i <; i ++) {getnate (getneat.). " +i);}}} Class Mythread는 스레드를 확장합니다 {private int i =; public mythread (runnable runnable) {super (runnable);}@atriadepublic void run () {system.out.println ("mythread run "); for (i =; i <; i ++) {thread.current (getthred) "" + i);}}} 마찬가지로, 런닝 가능한 인터페이스를 구현하는 스레드를 만드는 것도 마찬가지입니다. 차이점은
스레드 스레드 = 새로운 신화 (myrunnable);
그렇다면이 메소드가 새 스레드를 성공적으로 만들 수 있습니까? 대답은 예입니다. 현재 스레드 실행 본체의 경우, Myrunnable Interface 또는 Run () 메소드의 run () 메소드가 Mythread 클래스에서? 출력을 통해 스레드 실행 본체가 신화 클래스의 run () 메소드라는 것을 알고 있습니다. 실제로 스레드 클래스 자체가 런 가능한 인터페이스를 구현하고 run () 메소드가 먼저 실행 가능한 인터페이스에서 정의되기 때문에 그 이유는 매우 간단합니다.
공개 인터페이스 runnable {public Abstract void Run ();} 스레드 클래스의 Runnable 인터페이스에서 run () 메소드의 구현을 살펴 보겠습니다.
@overridepublic void run () {if (target! = null) {target.run ();}} 즉, 스레드 클래스에서 run () 메소드를 실행할 때 대상의 run () 메소드가 먼저 결정됩니다. 존재하는 경우 대상의 run () 메소드가 실행됩니다. 그러나 위에서 주어진 열에서 다형성의 존재로 인해 스레드 클래스의 run () 메소드는 전혀 실행되지 않지만 런타임 유형, 즉 Mythread 클래스의 run () 메소드가 직접 실행됩니다.
3. 호출 가능 및 향후 인터페이스를 사용하여 스레드를 만듭니다. 구체적으로, 호출 가능한 인터페이스에 대한 구현 클래스를 생성하고 Clall () 메소드를 구현합니다. FutureTask 클래스를 사용하여 Callable 구현 클래스 객체를 감싸고이 FutureTask 객체를 스레드 개체의 대상으로 사용하여 스레드를 생성하십시오.
조금 복잡해 보이지만 예제를 직접 보면 분명합니다.
공개 클래스 스레드 테스트 {public static void main (String [] args) {callable <integer> mycallable = new MyCallable (); // myCallable 객체 생성 futuretask <integer> ft = new FutureTask <integer> (myCallable); // futureTask를 사용하여 mycallable 객체를 랩핑합니다 (int i =; i <; i ++) {System.out.println (thread.currentThread (). getName () + "" + i); if (i ==) {스레드 스레드 = 새 스레드 (ft); // FutureTask 객체는 스레드 개체 스레드의 대상으로 새 스레드를 생성합니다 .Start (); // ready state}} system.out.println ( "루프 실행을위한 메인 스레드 ..."); try {int sum = ft.get (); // 새로 생성 된 새 스레드 시스템에서 Call () 메소드에 의해 반환 된 결과를 가져옵니다. out.println ( "sum =" + sum);} catch (e.printstacktrace ();} catch (executionException e) {e.printstacktrace ();}}}} classable <inte in int in int i = in inte in int in int in in int in in int in in in inte (e.printstacktrace ();}}}} catch (executionException e) 메소드, call () 메소드에는 @overridepublic integer call () {int sum =; for (; i <; i ++) {system.out.println (thread.currentthread (). getName () +"" +i); sum += i;} return sum;}}}}}}}}} 우선, Callable 인터페이스를 구현할 때 run () 메소드가 더 이상 run () 메소드가 아니라 call () 메소드임을 발견했습니다. 이 호출 () 메소드는 스레드 실행 본체이며 반환 값도 있습니다! 새 스레드를 만들 때 MyCallable 객체는 FutureTask를 통해 감싸고 스레드 객체의 대상으로 사용됩니다. 그런 다음 FutureTask 클래스의 정의를보십시오.
공개 클래스 FutureTask <v>는 runnableFuture <v> {// ....} 공개 인터페이스 runnableFuture <v> runnable, future <v> {void run ();}을 확장합니다. 따라서 FutureTask 클래스는 실제로 실행 가능하고 미래의 인터페이스를 모두 구현하여 미래의 이중 특성과 달리기가 가능하다는 것을 발견했습니다. 실행 가능한 기능을 통해 스레드 객체의 대상으로 사용할 수 있으며 향후 기능을 사용하면 새로 생성 된 스레드에서 Call () 메소드의 리턴 값을 얻을 수 있습니다.
이 프로그램을 실행 한 후에는 Sum = 4950이 항상 마지막 출력임을 알 수 있습니다. "루프의 기본 스레드가 실행되었습니다 ..."는 어린이 스레드 루프 중간에 출력 될 가능성이 높습니다. CPU의 스레드 스케줄링 메커니즘에서 "루프의 기본 스레드가 실행되었습니다 ..."의 출력 타이밍에 문제가 없다는 것을 알고 있습니다. 왜 합계 = 4950이 영원히 출력 될까요?
그 이유는 ft.get () 메소드를 통해 Child Thread의 Call () 메소드가 얻어지면 HILD 스레드의 메소드가 아직 실행되지 않았을 때 ft.get () 메소드가 반환 값을 얻기 전에 Call () 메소드가 실행될 때까지 차단되기 때문입니다.
위의 내용은 주로 세 가지 공통 스레드 생성 방법을 설명합니다. 스레드의 시작을 위해서는 모두 스레드 객체의 시작 () 메소드라고합니다. 동일한 스레드 객체에서 start () 메소드를 두 번 호출 할 수 없다는 점에 유의해야합니다.
III. Java Multithreading의 준비, 실행 및 죽음 상태
준비 상태는 실행중인 상태로 변환됩니다.이 스레드가 프로세서 리소스를 가져 오면;
실행 상태는 준비 상태로 변환됩니다.이 스레드가 수율 () 메소드를 적극적으로 호출하거나 실행 중에 프로세서 리소스를 잃을 때.
실행 상태는 죽은 상태로 변환됩니다. 스레드 실행 본체가 완료되거나 예외가 발생합니다.
여기서 스레드의 수율 () 메소드가 호출되면 스레드가 실행 상태에서 준비 상태로 전환되지만 CPU의 준비 상태에있는 스레드는 특정 임의성을 갖는다는 점에 유의해야합니다. 따라서 A 스레드가 수율 () 메소드를 호출 한 후에도 CPU가 여전히 A 스레드를 예약하는 것이 발생할 수 있습니다.
실제 비즈니스 요구로 인해 스레드를 특정 기회에서 종료 해야하는 경우가 종종 발생합니다. 현재 가장 일반적인 방법은 부울 변수를 설정하는 것입니다. 조건이 충족되면 스레드 실행 본체가 빠르게 실행됩니다. 좋다:
공개 클래스 스레드 테스트 {public static void main (string [] args) {myrunnable myrunnable = new Myrunnable (); 스레드 스레드 = 새 스레드 (myrunnable); for (int i =; i <; i ++) {system.out.println (stride.currentthread (). getName () + "; if (i ==); {strule.start ();} if (i ==) {myrunnable.stopthread ();}}} class myrunnable empless runnable {private boolean stop; @overridepublic void run () {for (int i =; i <&&! stop; i ++) {stuil.current (getthred ()). " + i);}} public void stopthread () {this.stop = true;}}위는 편집자가 소개 한 Java 스레드 멀티 스레딩에 대한 포괄적 인 분석입니다. 나는 그것이 당신에게 도움이되기를 바랍니다. 궁금한 점이 있으면 메시지를 남겨 주시면 편집자가 제 시간에 답장을 드리겠습니다. Wulin.com 웹 사이트를 지원해 주셔서 대단히 감사합니다!