CodeGym/Java Blog/무작위의/더 나은 조합: Java와 Thread 클래스. 파트 I — 실행 스레드
John Squirrels
레벨 41
San Francisco

더 나은 조합: Java와 Thread 클래스. 파트 I — 실행 스레드

무작위의 그룹에 게시되었습니다
회원

소개

멀티스레딩은 처음부터 Java에 내장되어 있었습니다. 이제 멀티스레딩이라는 것을 간단히 살펴보겠습니다. 더 나은 조합: Java와 Thread 클래스.  파트 I — 실행 스레드 - 1우리는 Oracle의 공식 강의를 참조점으로 삼습니다. " Lesson: The "Hello World!" Application ". Hello World 프로그램의 코드를 다음과 같이 약간 변경합니다.
class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello, " + args[0]);
    }
}
args프로그램이 시작될 때 전달되는 입력 매개변수의 배열입니다. 이 코드를 클래스 이름과 일치하고 확장자가 .java. javac 유틸리티를 사용하여 컴파일합니다 javac HelloWorldApp.java. . 그런 다음 "Roger"와 같은 매개 변수를 사용하여 코드를 실행합니다. java HelloWorldApp Roger 더 나은 조합: Java와 Thread 클래스.  파트 I — 실행 스레드 - 2현재 코드에 심각한 결함이 있습니다. 인수를 전달하지 않으면(예: "java HelloWorldApp"만 실행) 오류가 발생합니다.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
        at HelloWorldApp.main(HelloWorldApp.java:3)
"main" 스레드에서 예외(예: 오류)가 발생했습니다. 그렇다면 Java에는 스레드가 있습니까? 이것이 우리의 여정이 시작되는 곳입니다.

자바와 쓰레드

스레드가 무엇인지 이해하려면 Java 프로그램이 시작되는 방식을 이해해야 합니다. 다음과 같이 코드를 변경해 보겠습니다.
class HelloWorldApp {
    public static void main(String[] args) {
		while (true) {
			// Do nothing
		}
	}
}
이제 다시 javac. 편의상 별도의 창에서 Java 코드를 실행합니다. Windows에서는 다음과 같이 수행할 수 있습니다. start java HelloWorldApp. 이제 jps 유틸리티를 사용하여 Java가 알려줄 수 있는 정보를 확인합니다. 더 나은 조합: Java와 Thread 클래스.  파트 I — 실행 스레드 - 3첫 번째 숫자는 PID 또는 프로세스 ID입니다. 프로세스란 무엇입니까?
A process is a combination of code and data sharing a common virtual address space.
프로세스를 사용하면 서로 다른 프로그램이 실행될 때 서로 격리됩니다. 각 응용 프로그램은 다른 프로그램을 방해하지 않고 자체 메모리 영역을 사용합니다. 자세한 내용은 이 자습서를 읽는 것이 좋습니다: Processes and Threads . 프로세스는 스레드 없이 존재할 수 없으므로 프로세스가 존재하면 적어도 하나의 스레드가 있습니다. 그러나 이것은 Java에서 어떻게 발생합니까? Java 프로그램을 시작할 때 실행은 메서드로 시작됩니다 main. 마치 우리가 프로그램에 들어가는 것과 같기 때문에 이 특별한 main방법을 진입점이라고 합니다. 메소드는 mainJVM(Java Virtual Machine)이 프로그램 실행을 시작할 수 있도록 항상 "public static void"여야 합니다. 자세한 내용은 Java 기본 메서드가 정적인 이유는 무엇입니까?. Java 시작 관리자(java.exe 또는 javaw.exe)는 간단한 C 응용 프로그램으로 밝혀졌습니다. 실제로 JVM을 구성하는 다양한 DLL을 로드합니다. Java 시작 프로그램은 특정 JNI(Java Native Interface) 호출 집합을 만듭니다. JNI는 Java 가상 머신의 세계와 C++의 세계를 연결하는 메커니즘입니다. 따라서 런처는 JVM 자체가 아니라 이를 로드하는 메커니즘입니다. JVM을 시작하기 위해 실행할 올바른 명령을 알고 있습니다. JNI 호출을 사용하여 필요한 환경을 설정하는 방법을 알고 있습니다. 이 환경 설정에는 물론 "main"이라고 하는 기본 스레드를 만드는 작업이 포함됩니다. Java 프로세스에 어떤 스레드가 있는지 더 잘 설명하기 위해 jvisualvm 을 사용합니다.JDK에 포함된 도구입니다. 프로세스의 pid를 알면 해당 프로세스에 대한 정보를 즉시 볼 수 있습니다. jvisualvm --openpid <process id> 더 나은 조합: Java와 Thread 클래스.  파트 I — 실행 스레드 - 4흥미롭게도 각 스레드는 프로세스에 할당된 메모리에 자체 별도 영역이 있습니다. 이 메모리 구조를 스택이라고 합니다. 스택은 프레임으로 구성됩니다. 프레임은 메서드의 활성화(완료되지 않은 메서드 호출)를 나타냅니다. 프레임은 StackTraceElement로 표시될 수도 있습니다( StackTraceElement 용 Java API 참조 ). " How does Java (JVM) allocate stack for each thread " 토론에서 각 스레드에 할당된 메모리에 대한 자세한 정보를 찾을 수 있습니다 . Java API를 보고 "Thread"라는 단어를 검색하면 java.lang.Thread를 찾을 수 있습니다.수업. 이것은 Java에서 스레드를 나타내는 클래스이며 이를 사용하여 작업해야 합니다. 더 나은 조합: Java와 Thread 클래스.  파트 I — 실행 스레드 - 5

java.lang.Thread

Java에서 스레드는 클래스의 인스턴스로 표시됩니다 java.lang.Thread. Thread 클래스의 인스턴스 자체가 실행 스레드가 아님을 즉시 이해해야 합니다. 이것은 JVM과 운영 체제에서 관리하는 하위 수준 스레드를 위한 일종의 API일 뿐입니다. Java 런처를 사용하여 JVM을 시작하면 main"main"이라는 스레드와 몇 가지 다른 하우스키핑 스레드가 생성됩니다. Thread 클래스에 대한 JavaDoc에 명시된 바와 같이: When a Java Virtual Machine starts up, there is usually a single non-daemon thread. 스레드에는 데몬과 비 데몬의 두 가지 유형이 있습니다. 데몬 스레드는 백그라운드에서 일부 작업을 수행하는 백그라운드(하우스키핑) 스레드입니다. "daemon"이라는 단어는 Maxwell의 악마를 나타냅니다. 이 Wikipedia 기사 에서 자세한 내용을 확인할 수 있습니다 . 문서에 명시된 바와 같이 JVM은 다음이 될 때까지 프로그램(프로세스) 실행을 계속합니다.
  • Runtime.exit () 메서드가 호출됩니다.
  • 모든 NON-daemon 스레드가 작업을 완료합니다(오류 없이 또는 예외 발생 없이).
다음은 중요한 세부 사항입니다. 데몬 스레드는 언제든지 종료될 수 있습니다. 결과적으로 데이터의 무결성에 대한 보장이 없습니다. 따라서 데몬 스레드는 특정 하우스키핑 작업에 적합합니다. 예를 들어 Java에는 메서드 호출 처리를 담당하는 스레드 finalize(), 즉 가비지 수집기(gc)와 관련된 스레드가 있습니다. 각 스레드는 그룹( ThreadGroup )의 일부입니다. 그리고 그룹은 다른 그룹의 일부가 되어 특정 계층 구조나 구조를 형성할 수 있습니다.
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());
}
그룹은 스레드 관리에 질서를 부여합니다. 그룹 외에도 스레드에는 자체 예외 처리기가 있습니다. 예를 살펴보십시오.
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);
}
0으로 나누면 핸들러에서 오류가 발생합니다. 자체 핸들러를 지정하지 않으면 JVM이 기본 핸들러를 호출하여 예외의 스택 추적을 StdError로 출력합니다. 각 스레드에는 우선 순위도 있습니다. 이 문서에서 우선 순위에 대해 자세히 알아볼 수 있습니다. 다중 스레딩의 Java 스레드 우선 순위 .

스레드 생성

문서에 명시된 바와 같이 스레드를 생성하는 방법에는 두 가지가 있습니다. 첫 번째 방법은 자신만의 하위 클래스를 만드는 것입니다. 예를 들어:
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();
    }
}
보시다시피 작업의 작업은 run()메소드에서 발생하지만 스레드 자체는 start()메소드에서 시작됩니다. 이 방법을 혼동하지 마십시오. r 방법을 직접 호출하면 un()새 스레드가 시작되지 않습니다. start()JVM에게 새로운 쓰레드 생성을 요청하는 메소드 이다 . Thread를 상속하는 이 옵션은 클래스 계층 구조에 Thread를 포함한다는 점에서 이미 좋지 않습니다. 두 번째 단점은 우리가 "단일 책임" 원칙을 위반하기 시작했다는 것입니다. 즉, 우리 클래스는 스레드 제어와 이 스레드에서 수행할 일부 작업을 동시에 담당합니다. 올바른 방법은 무엇입니까? 답은 run()우리가 재정의하는 동일한 방법에서 찾을 수 있습니다.
public void run() {
	if (target != null) {
		target.run();
	}
}
다음은 Thread 클래스의 인스턴스를 생성할 때 전달할 수 있는 targetsome 입니다 . java.lang.Runnable이는 다음과 같이 할 수 있음을 의미합니다.
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();
    }
}
Runnable또한 Java 1.8 이후 기능적 인터페이스였습니다. 이를 통해 스레드 작업에 대해 훨씬 더 아름다운 코드를 작성할 수 있습니다.
public static void main(String[] args) {
	Runnable task = () -> {
		System.out.println("Hello, World!");
	};
	Thread thread = new Thread(task);
	thread.start();
}

결론

이 논의를 통해 스레드가 무엇인지, 스레드가 어떻게 존재하는지, 스레드로 수행할 수 있는 기본 작업이 무엇인지 명확해졌으면 합니다. 다음 파트 에서는 ​​스레드가 서로 상호 작용하는 방식을 이해하고 스레드 수명 주기를 살펴보겠습니다. 더 나은 조합: Java와 Thread 클래스. 2부 — 동기화 함께 하면 더 좋습니다: Java와 Thread 클래스. 3부 — 상호 작용 더 나은 조합: Java와 Thread 클래스. 4부 — 호출 가능, 미래 및 친구 더 나은 조합: Java 및 Thread 클래스. 파트 V — Executor, ThreadPool, Fork/Join 더 나은 조합: Java 및 Thread 클래스. 6부 — 발사!
코멘트
  • 인기
  • 신규
  • 이전
코멘트를 남기려면 로그인 해야 합니다
이 페이지에는 아직 코멘트가 없습니다