1. 프로세스 및 스레드
1. 프로세스는 무엇입니까?
좁은 정의 : 프로세스는 실행중인 컴퓨터 프로그램의 인스턴스입니다.
일반적인 정의 : 프로세스는 특정 데이터 세트와 관련하여 특정 독립적 인 기능을 갖춘 프로그램의 실행 활동입니다. 운영 체제의 동적 실행의 기본 단위입니다. 기존 운영 체제에서 프로세스는 기본 할당 장치 및 기본 실행 장치입니다.
2. 스레드 란 무엇입니까?
가벼운 프로세스 (LWP)라고도하는 스레드는 프로그램 실행 흐름의 가장 작은 단위입니다. 표준 스레드는 스레드 ID, 현재 명령 포인터 (PC), 레지스터 세트 및 스택으로 구성됩니다. 또한 스레드는 프로세스의 엔티티이며 시스템에 의해 독립적으로 예약되고 발송되는 기본 장치입니다. 스레드 자체는 시스템 리소스를 소유하지 않지만 작동 중에 몇 가지 필수 리소스 만 있지만 프로세스가 소유 한 모든 리소스를 동일한 프로세스에 속하는 다른 스레드와 공유 할 수 있습니다.
3. 프로세스와 스레드의 차이점은 무엇입니까?
프로세스와 스레드의 주요 차이점은 운영 체제 자원 관리 방법이 다르다는 것입니다.
프로세스에는 독립적 인 주소 공간이 있습니다. 프로세스 충돌 후에는 보호 모드의 다른 프로세스에 영향을 미치지 않으며 스레드는 프로세스에서 다른 실행 경로 일뿐입니다.
스레드에는 자체 스택과 로컬 변수가 있지만 스레드간에 별도의 주소 공간은 없습니다. 스레드가 죽으면 전체 프로세스가 죽음을 의미합니다. 따라서 다중 프로세스 프로그램은 다중 스레드 프로그램보다 강력하지만 프로세스를 전환 할 때 더 많은 리소스를 소비하고 효율적입니다. 그러나 특정 변수를 공유 해야하는 동시 작업이 필요한 동시 작업의 경우 프로세스가 아닌 스레드 만 사용할 수 있습니다.
요컨대, 스레드와 프로세스의 차이점은 다음과 같습니다.
(1) 프로그램은 하나 이상의 프로세스를 가지고 있으며 프로세스에는 적어도 하나의 스레드가 있습니다.
(2) 스레드의 분할 척도는 프로세스보다 작으므로 다중 스레드 프로그램의 동시성이 높아집니다.
(3) 프로세스는 실행 중에 독립적 인 메모리 유닛을 가지고 있으며 여러 스레드는 메모리를 공유하여 프로그램의 작동 효율성을 크게 향상시킵니다.
(4) 실행 중 스레드와 프로세스 사이에는 차이가 있습니다. 각 독립 스레드에는 프로그램 실행을위한 항목, 일련의 실행 및 프로그램 종료가 있습니다. 그러나 스레드는 독립적으로 실행할 수 없으며 응용 프로그램에 존재해야하며 응용 프로그램에서 여러 스레드 실행 컨트롤이 제공됩니다.
(5) 논리적 관점에서 볼 때, 멀티 스레딩의 의미는 응용 프로그램에서 여러 실행 부품을 동시에 실행할 수 있다는 것입니다. 그러나 운영 체제는 여러 스레드를 프로세스 일정, 관리 및 리소스 할당을 실현하기위한 여러 독립 응용 프로그램으로 간주하지 않습니다.
이것은 프로세스와 스레드의 중요한 차이입니다.
2. 실의 수명주기와 5 개의 기본 상태
자바 스레드에는 5 가지 기본 상태가 있습니다.
(1) 새 상태 (신규) : 스레드 객체 쌍이 생성되면 다음과 같은 새로운 상태로 들어갑니다. 스레드 t = new Mythread ();
(2) 준비 상태 (runnable) : 스레드 개체 (t.start ();)의 start () 메소드가 있으면 스레드가 준비 상태로 들어갑니다. 준비 상태의 스레드는 스레드가 준비되었고 CPU가 언제든지 실행을 일정하기를 기다리고 있음을 의미합니다.
(3) 실행 상태 : CPU가 준비 상태에서 스레드를 예약하기 시작하면 스레드를 진정으로 실행할 수 있습니다. 즉, 실행 상태로 들어갑니다. 참고 : 준비 상태는 실행중인 상태에 대한 유일한 항목입니다. 즉, 스레드가 실행 상태에 입력하려면 먼저 준비 상태에 있어야합니다.
(4) 차단 된 상태 : 어떤 이유로 든 실행 상태의 스레드는 일시적으로 CPU 사용을 포기하고 실행을 중지합니다. 현재 블로킹 상태로 들어갑니다. CPU가 다시 실행중인 상태에 들어가기 위해 다시 전화 할 기회가 없습니다. 차단 이유에 따라 차단 상태를 세 가지 유형으로 나눌 수 있습니다.
① 차단 대기 : 실행중인 상태의 스레드는 대기 상태를 대기 상태로 입력하기 위해 Wait () 메소드를 실행합니다.
synchronized 차단 : 스레드는 동기화 된 동기화 잠금을 얻지 못하며 (잠금이 다른 스레드에 의해 점유되어 있기 때문에) 동기화 된 차단 상태로 들어갑니다.
heother 차단 : 스레드의 sleep () 또는 join ()을 호출하거나 I/O 요청을 보낼 때 스레드가 차단 상태로 들어갑니다. Sleep () State가 시간이 초과되면 join ()는 스레드가 끝나거나 시간이 끝나기를 기다렸거나 I/O 처리가 완료되면 스레드가 준비 상태에 다시 들어갔습니다.
(5) 죽은 상태 : 스레드가 예외로 인해 실행 () 메소드를 실행하거나 종료했으며 스레드는 수명주기를 종료합니다.
3. Java Multithreading의 구현
Java에서는 멀티 스레드 프로그램을 구현하려면 스레드의 메인 클래스 (스레드의 주요 클래스를 나타내는 메인 클래스의 개념과 같이)에 의존해야하지만,이 스레드의 주요 클래스는 그것을 정의 할 때 특별한 요구 사항을 가져야합니다. 이 클래스는 스레드 클래스를 상속하거나 실행 가능한 인터페이스를 구현하여 정의를 완료 할 수 있습니다.
1. 스레드 클래스를 상속하여 멀티 스레딩을 구현하십시오
java.lang.thread는 스레드 작업을 담당하는 클래스입니다. 스레드 클래스를 상속하면 모든 클래스가 스레드의 주요 클래스가 될 수 있습니다. 메인 클래스이므로 사용 방법이 있어야하며 스레드에서 시작한 기본 메소드는 스레드 클래스에서 run () 메소드를 덮어 쓰기 위해 필요합니다.
스레드의 신체 클래스 정의 :
클래스 Mythread는 스레드를 확장합니다 {// 스레드 개인 문자열 제목의 메인 클래스; 공개 신화 (문자열 제목) {this.title = title; } @override public void run () {// 스레드의 주요 메소드 (int x = 0; x <10; x ++) {system.out.println (this.title + "run, x =" + x); }}}스레드 클래스가 있고 해당 조작 방법이 있으므로 객체를 생성하고 내부의 메소드를 호출해야하므로 다음 프로그램이 작성됩니다.
public class testdemo {public static void main (string [] args) {mythread mt1 = new Mythread ( "스레드 A"); Mythread MT2 = New Mythread ( "스레드 B"); Mythread MT3 = New Mythread ( "스레드 C"); mt1.run (); mt2.run (); mt3.run (); }실행 결과 :
실행을 실행하십시오, x = 0
실행을 실행, x = 1
실행을 실행, x = 2
실행을 실행, x = 3
실행을 실행, x = 4
실행을 실행, x = 5
실행을 실행, x = 6
실행을 실행, x = 7
실행을 실행하십시오, x = 8
실행을 실행, x = 9
스레드 B가 실행, x = 0입니다
스레드 B가 실행, x = 1
스레드 B가 실행, x = 2
스레드 B가 실행, x = 3
스레드 B가 실행, x = 4
스레드 B가 실행, x = 5
스레드 B가 실행, x = 6
스레드 B가 실행, x = 7
스레드 B가 실행, x = 8
스레드 B가 실행, x = 9
스레드 C는 x = 0입니다
스레드 C 실행, x = 1
스레드 C 실행, x = 2
스레드 C 실행, x = 3
스레드 C 실행, x = 4
스레드 C 실행, x = 5
스레드 C 실행, x = 6
스레드 C 실행, x = 7
스레드 C 실행, x = 8
스레드 C 실행, x = 9
여러 스레드의 실행이 교대로 실행되어야하기 때문에 위의 작업이 실제로 다중 스레딩을 시작하지 않는다는 것을 발견했습니다. 현재 순차적으로 실행되며 각 객체의 코드가 실행 된 후 각 객체의 코드가 계속 실행됩니다.
프로그램에서 진정으로 멀티 스레딩을 시작하려면 Thread 클래스의 메소드 : public void start ()에 의존해야합니다. 즉, 멀티 스레딩을 시작합니다. 이 메소드를 호출하면 run () 메소드가 간접적으로 호출됩니다.
public class testdemo {public static void main (string [] args) {mythread mt1 = new Mythread ( "스레드 A"); Mythread MT2 = New Mythread ( "스레드 B"); Mythread MT3 = New Mythread ( "스레드 C"); mt1.start (); mt2.start (); mt3.start (); }}실행 결과 :
스레드 C는 x = 0입니다
실행을 실행하십시오, x = 0
스레드 B가 실행, x = 0입니다
실행을 실행, x = 1
스레드 C 실행, x = 1
실행을 실행, x = 2
스레드 B가 실행, x = 1
실행을 실행, x = 3
실행을 실행, x = 4
실행을 실행, x = 5
스레드 C 실행, x = 2
스레드 C 실행, x = 3
스레드 C 실행, x = 4
스레드 C 실행, x = 5
스레드 C 실행, x = 6
스레드 C 실행, x = 7
스레드 C 실행, x = 8
스레드 C 실행, x = 9
실행을 실행, x = 6
실행을 실행, x = 7
실행을 실행하십시오, x = 8
실행을 실행, x = 9
스레드 B가 실행, x = 2
스레드 B가 실행, x = 3
스레드 B가 실행, x = 4
스레드 B가 실행, x = 5
스레드 B가 실행, x = 6
스레드 B가 실행, x = 7
스레드 B가 실행, x = 8
스레드 B가 실행, x = 9
현재 여러 스레드가 서로 교대로 실행된다는 것을 알 수 있지만 각 실행 결과는 다릅니다. 위의 코드를 통해 결론을 도출 할 수 있습니다. 스레드를 시작하려면 실행하려면 스레드 클래스의 시작 () 메소드에 의존해야합니다. 스레드가 시작되면 기본적으로 run () 메소드가 호출됩니다.
start () 메소드를 호출 한 후 일련의 복잡한 일이 일어났습니다.
(1) 새 실행 스레드 (새 통화 스택 포함)를 시작합니다.
(2) 실은 새로운 상태에서 달리기 가능한 상태로 전송된다.
(3) 스레드가 실행 기회를 얻으면 대상 run () 메소드가 실행됩니다.
참고 : Java의 경우 run () 메소드에는 특별한 것이 없습니다. Main () 메소드와 마찬가지로 새 스레드는 통화의 메소드 이름 (및 서명)을 알고 있음을 의미합니다. 따라서 Runnable 또는 Thread에서 실행 메소드를 호출하는 것이 합법적이지만 새 스레드를 시작하지는 않습니다.
설명 : 스레드가 시작될 때 run ()을 직접 호출하는 대신 시작 ()을 호출 해야하는 이유는 무엇입니까?
start ()를 호출 한 후 실제로 재정의 run () 메소드를 실행하므로 run () 메소드를 직접 호출하지 않겠습니까? 이 문제를 설명하려면 스레드 클래스의 소스 코드를 열고 시작 () 메소드의 정의를 관찰하십시오.
public synchronized void start () {if (ThreadStatus! = 0) 새 불법 스레드 스테이트 exception (); group.add (this); 부울 시작 = 거짓; try {start0 (); 시작 = 참입니다. } 마침내 {try {if (! start) {group.threadStartFailed (this); }} catch (Throwable incore) {}}} 개인 기본 void start0 ();이 메소드의 소스 코드를 열면 먼저이 메소드가 "불법 스레드 스테이트 exception"예외를 던지는 것을 알게됩니다. 일반적으로, 메소드가 던지기를 사용하여 예외 객체를 사용하는 경우,이 예외는 시도 ... 잡기를 사용하거나 메소드 선언에 던져진 것을 사용하여 던져야하지만이 영역에는 아무것도 없습니다. 왜? 이 예외 클래스는 런타임 예외 (runtimeexception)의 서브 클래스에 속하기 때문에 :
java.lang.object
|- java.lang.throwable
|- java.lang.exception
| -java.lang.runtimeexception
|- java.lang.illegalargumentexception
|- java.lang.ilegalthreadstateException
이 예외는 스레드 객체를 반복적으로 시작할 때, 즉 스레드 객체를 한 번만 시작할 수 있습니다.
start () 메소드의 가장 중요한 부분 중 하나는 start0 () 메소드 이며이 메소드는 기본 키워드 정의를 사용합니다.
기본 키워드는 Java Native Interface, 즉 Java가 기본 운영 체제의 기능 기능을 호출하여 일부 특수 작업을 완료하는 데 사용됩니다. Java의 가장 큰 특징은 휴대 성이기 때문에 이러한 코드 개발은 Java에서 거의 거의 볼 수 없습니다. 고정 된 운영 체제에서만 프로그램을 사용할 수있는 경우 휴대 성이 완전히 손실 되므로이 작업은 일반적으로 사용되지 않습니다.
멀티 스레딩 구현에는 운영 체제의 지원이 필요합니다. 위의 start0 () 메소드는 실제로 메소드 본문이없는 추상 메소드와 매우 유사합니다. 이 방법 본문은 구현하기 위해 JVM에 양도되어 있습니다.
따라서 다중 스레드 작업에서 start () 메소드를 사용하여 START를 사용하여 다중 스레드 작업에는 운영 체제 기능 호출이 필요합니다.
2. 멀티 스레딩을 구현하려면 런닝 가능한 인터페이스를 구현하십시오
스레드 클래스를 사용하면 실제로 다중 스레딩 구현을 용이하게 할 수 있지만이 방법의 가장 큰 단점은 단일 상속 문제입니다. 이를 위해, 런닝 가능한 인터페이스를 Java에서 사용하여 멀티 스레딩을 구현할 수 있습니다. 이 인터페이스의 정의는 다음과 같습니다.
공개 인터페이스 runnable {public void run ();}런닝 가능한 인터페이스를 통해 멀티 스레딩 구현 :
클래스 신화는 실행 가능한 {// 스레드의 메인 클래스 비공개 문자열 제목; 공개 신화 (문자열 제목) {this.title = title; } @override public void run () {// 스레드의 기본 메소드 (int x = 0; x <10; x ++) {System.out.println (this.title + "run, x =" + x); }}}이것은 스레드 클래스를 상속하는 이전의 방식과 크게 다르지 않지만 한 가지 장점은 단일 상속의 한계를 피한다는 것입니다.
그러나 문제는 여기 있습니다. 앞에서 언급했듯이 멀티 스레딩을 시작하려면 스레드 클래스의 시작 () 메소드에 의존해야합니다. 스레드 클래스를 상속하면이 방법을 직접 상속하고 사용할 수 있습니다. 그러나 지금 당신은 실행 가능한 인터페이스를 구현하고 있습니다. 이 방법이 없으면 상속받을 수 있습니다. 당신은 무엇을해야합니까?
이 문제를 해결하려면 스레드 클래스에 의존하여 완료해야합니다. 생성자는 스레드 클래스에 정의되어 실행 가능한 인터페이스 개체를 수신합니다.
공개 스레드 (Runnable Target);
스레드 클래스를 사용하여 멀티 스레딩 시작 :
public class testdemo {public static void main (string [] args)은 예외 {mythread mt1 = new Mythread ( "Thread a"); Mythread MT2 = New Mythread ( "스레드 B"); Mythread MT3 = New Mythread ( "스레드 C"); 새 스레드 (mt1) .start (); 새 스레드 (mt2) .start (); 새 스레드 (mt3) .start (); }}실행 결과 :
실행을 실행하십시오, x = 0
스레드 B가 실행, x = 0입니다
스레드 B가 실행, x = 1
스레드 C는 x = 0입니다
스레드 B가 실행, x = 2
실행을 실행, x = 1
스레드 B가 실행, x = 3
스레드 C 실행, x = 1
스레드 C 실행, x = 2
스레드 B가 실행, x = 4
스레드 B가 실행, x = 5
실행을 실행, x = 2
실행을 실행, x = 3
실행을 실행, x = 4
실행을 실행, x = 5
실행을 실행, x = 6
실행을 실행, x = 7
실행을 실행하십시오, x = 8
실행을 실행, x = 9
스레드 B가 실행, x = 6
스레드 B가 실행, x = 7
스레드 B가 실행, x = 8
스레드 B가 실행, x = 9
스레드 C 실행, x = 3
스레드 C 실행, x = 4
스레드 C 실행, x = 5
스레드 C 실행, x = 6
스레드 C 실행, x = 7
스레드 C 실행, x = 8
스레드 C 실행, x = 9
현재 다중 스레드 스타트 업뿐만 아니라 단일 상속 제한도 달성되지 않습니다.
3. 멀티 스레딩을 구현하는 세 번째 방법 : 호출 가능한 인터페이스를 사용하여 멀티 스레딩을 구현하십시오.
런닝 가능한 인터페이스를 사용한 다중 스레딩은 단일 상속 제한을 피할 수 있지만, 런닝 가능한 인터페이스의 run () 메소드가 작동 결과를 반환 할 수없는 문제가 있습니다. 이 문제를 해결하기 위해 새로운 인터페이스가 제공됩니다 : Callable 인터페이스 (java.util.concurrent.callable).
public interface callable <v> {public v call ()은 예외를 던지려고합니다;}Callable 인터페이스에서 Call () 메소드를 실행하면 결과가 반환됩니다. 반환 된 결과 유형은 호출 가능한 인터페이스의 제네릭에 의해 결정됩니다.
멀티 스레딩을 구현하기 위해 호출 가능한 인터페이스 구현의 특정 작동은 다음과 같습니다.
Callable 인터페이스의 구현 클래스를 작성하고 Clall () 메소드를 구현하십시오. 그런 다음 FutureTask 클래스를 사용하여 Callable 구현 클래스의 객체를 감싸고이 FutureTask 객체를 스레드 객체의 대상으로 사용하여 스레드를 만듭니다.
스레드 바디 클래스 정의 :
import java.util.concurrent.callable; 클래스 신화 구현 호출 가능 <string> {private int ticket = 10; @override public string ()는 exception {for (int i = 0; i <20; i ++) {if (this.ticket> 0) {System.out.println ( "티켓 판매, 나머지 투표 수는"+this.ticket -); }} 반품 "티켓이 매진되었습니다"; }}스레드 클래스는 호출 가능한 인터페이스를 직접 지원하지 않습니다. JDK1.5 후에는 클래스가 제공됩니다.
java.util.concurrent.futuretask <v>
이 클래스는 주로 호출 가능한 인터페이스 객체의 작동을 담당합니다. 정의 구조는 다음과 같습니다.
공개 클래스 FutureTask <v>
객체를 확장합니다
RunnableFurture <v>를 구현합니다
RunnableFurture 인터페이스에는 다음과 같은 정의가 있습니다.
공개 인터페이스 runnablefurture <v>
런닝 가능, 미래 <v>
다음 생성자는 FutureTask 클래스에 정의되어 있습니다.
공개 futuretask (Callable <v> 호출 가능)
이제 FutureTask 클래스를 통해 마지막으로 호출 가능한 인터페이스 객체를받을 수 있습니다. 수신의 목적은 Call () 메소드의 반환 결과를 얻는 것입니다.
위의 분석에서 우리는 다음을 찾을 수 있습니다.
FutureTask 클래스는 호출 가능한 인터페이스 객체를받을 수 있으며 FutureTask 클래스는 RunnableFurture 인터페이스를 구현하여 런닝 가능한 인터페이스를 상속합니다.
따라서 다음과 같이 멀티 스레딩을 시작할 수 있습니다.
Public Class TestDemo {public static void main (String [] args)은 예외 {mythread mt1 = new Mythread (); 신화 mt2 = new Mythread (); FutureTask <string> task1 = new FutureTask <string> (mt1); // get get call () 메소드 결과를 반환하여 futuretask <string> task2 = new futuretask <string> (mt2); // get get call () method를 반환합니다. 스레드 클래스 구성을 사용하여 작업 객체 새 스레드 (task1) .start (); 새 스레드 (task2) .start (); // multithread execution이 완료되면 FutureTask의 상위 인터페이스 미래의 get () 메소드를 사용하여 실행 결과 시스템을 얻을 수 있습니다. System.out.println ( "스레드 2의 리턴 결과 :"+task2.get ()); }}실행 결과 :
티켓 판매, 나머지 투표 수는 10입니다
티켓 판매, 나머지 투표 수는 10입니다
티켓 판매, 나머지 투표 수는 9입니다
티켓 판매, 나머지 투표 수는 8입니다
티켓 판매, 나머지 투표 수는 7입니다
티켓 판매, 나머지 투표 수는 9입니다
티켓 판매, 나머지 투표 수는 6입니다
티켓 판매, 나머지 투표 수는 8입니다
티켓 판매, 나머지 투표 수는 5입니다
티켓 판매, 나머지 투표 수는 7입니다
티켓 판매, 나머지 투표 수는 4입니다
티켓 판매, 나머지 투표 수는 6입니다
티켓 판매, 나머지 투표 수는 3입니다
티켓 판매, 나머지 투표 수는 5입니다
티켓 판매, 나머지 투표 수는 2입니다
티켓 판매, 나머지 투표 수는 4입니다
티켓 판매, 나머지 투표 수는 1입니다
티켓 판매, 나머지 투표 수는 3입니다
티켓 판매, 나머지 투표 수는 2입니다
티켓 판매, 나머지 투표 수는 1입니다
스레드 1 : 티켓이 매진되었습니다. 스레드 2 : 티켓이 매진되었습니다.
요약:
위의 내용은 멀티 스레딩을 구현하는 세 가지 방법을 설명합니다. 스레드 시작의 경우 모두 스레드 객체의 시작 () 메소드라고합니다. 동일한 스레드 객체에서 start () 메소드를 두 번 호출 할 수 없다는 점에 유의해야합니다.