스레드의 수명주기와 공통점 API의 상태에 이전 기사에서 우리는 해설자가 있었다. 이 문서의 구축 방법에 대한 설명에 집중되기 시작했다 우리가 시작 방법은 스레드를 시작할 수 있습니다 부르는 이유, 그것은 또한 발표 될 예정이다.
첫째, 데몬 스레드 및 비 데몬 스레드
우리는 스레드를 실행하는 자바 가상 머신이 될 때 기본이 우리의 서비스에 대한 스레드 몇 가지 다른 스레드를 시작하기 때문입니다, 스레드 ID는 모든 시간이 0이 아닌 시간을 찾을 수. 그리고 기본적으로 생성 된 스레드는 구별이 우리 자신의 만들 수 있습니다. 비 데몬 데몬 스레드와 스레드를 구별하는 것이 필요하다.
1. 데몬 스레드 및 비 데몬 스레드는 무엇입니까?
이 기본 시작 스레드는 그는 구체적으로 몇 가지 배경 작업 처리, 데몬 스레드입니다. 그래서 예를 들어, 쓰레기 수집 및하십시오. 이 비 데몬 스레드는 우리 자신의 창조의 스레드입니다. 공식 문서는 자바 가상 머신없는 비 데몬 스레드와 스레드가 디폴트를 종료 할 때, 상태. 예를 들어, 당신은 이해할 수있다 :
호텔 직원 내부 데몬 스레드와 마찬가지로, 고객과 같은 비 데몬 스레드, 고객은 더 수반 이상 필요가 아니다.
2, 코드를 보여줍니다
우리는 자신의 역할을 설명하기 위해 코드를 통해 볼
public class Test {
public static void main(String[] args) {
Thread thread = new Thread(()->{
while (true) {
System.out.println("无限循环");
}
}) ;
thread.start();
}
}
复制代码
여기에 두 가지 스레드가 메인 스레드가되어 있으며, 두 번째 스레드는 자신을 생성됩니다. 실행 한 후에는 스레드가 아닌 데몬 스레드 때문에 프로그램의 구현, 라디오에 갈 것이 분명하다. 실행도 메인 스레드는 스레드 실행의 마지막이 될 것입니다. 데몬 스레드가 동일하지 않은 것처럼 이제 우리는 스레드를 설정합니다.
public class Test {
public static void main(String[] args) {
Thread thread = new Thread(()->{
while (true) {
System.out.println("无限循环");
}
}) ;
//设置为守护线程
thread.setDaemon(true);
thread.start();
}
}
复制代码
다시 실행, 우리는 우리가 스레드가 데몬 스레드 된 설정 때문입니다, 정상적인 절차에서 그것을 발견 할 것이다, 당신은 지금 웨이터,없이 고객이되었다 메인 스레드와 스레드에 대해 생각, 그래서이 데몬 스레드 쇼핑 나는 주위를 배회 왼쪽했다.
3, 데몬 스레드 시나리오?
당신이 데몬 스레드의 특성을 이해 한 후, 당신은 JVM을 종료하는 것도 따라 일부 스레드를 철회하고 싶었다 때와 예기치 못한 일을 수행하기 위해이 원리를 사용하여, 당신은 그를 데몬 스레드로 설정 넣을 수 있습니다.
개념의 기본적인 이해 후 우리는 생성자 스레드 봐.
둘째, 스레드 생성자
1 생성자
스레드 스레드 생성자는 총 8가
여기에서 우리는 새로운 클래스 쓰레드 그룹과 접촉. 가 나타내는 의미하는 것은 스레드가 스레드 그룹에 속하는 것입니다. 스레드는 또한 실행 가능한 인터페이스를 선언 할 수 있습니다, 스레드 그룹이 속하는 지정할 수 있습니다 때 위에서 우리는 스레드의 예에서 볼 수 있습니다. 의이 thread 그룹 쓰레드 그룹을 분석해 보겠습니다.
두 사람 사이의 관계는 이러한 방식으로 표현 될 수있다 :
상기에서 스레드 그룹, 우리가 당신에게 코드를 보여 우리가 어디 스레드를 지정할 수있다.
public class Test {
public static void main(String[] args) {
//为当前线程设置线程组
ThreadGroup group= new ThreadGroup("线程组");
Thread thread = new Thread(group,"当前线程");
thread.start();
System.out.print(thread.getThreadGroup().getName());
}
}
//输出:线程组
复制代码
이것은 기본적인 사용법이지만, 우리가 지정된 스레드 그룹 출력 스레드에 속하지 않는 경우 어떤 결과가 될 것인가? 테스트 :
public class Test {
public static void main(String[] args) {
ThreadGroup group= new ThreadGroup("线程组");
ThreadGroup maingroup = Thread.currentThread().getThreadGroup();
Thread thread1 = new Thread(group,"线程A");
Thread thread2 = new Thread("线程B");
System.out.println(thread1.getThreadGroup().getName());
System.out.println(thread2.getThreadGroup().getName());
System.out.println(maingroup.getName());
}
}
//输出:线程组 main main
复制代码
위의 코드의 평균 maingroup 메인 스레드 그룹이이 스레드에게 우리가 만든 스레드 그룹, 기본 스레드 B 스레드 그룹을 지정합니다. 출력은 다음 그와 그의 아버지의 스레드 그룹이 동일 스레드 스레드 그룹을 지정하지 않을 경우 우리가 찾을 수 있음을 나타냅니다.
2, 스레드 인스턴스화
팔 개 생성자 스레드 이상을 감안할 때, 우리는 스레드를 인스턴스화하는 이들 8 개 생성자를 사용할 수 있지만, 바닥은 그것을 수행하는 방법인가? 그것은 그게의 예와 같은 일반적인 범주로 될 수 있을까? 이 점에서 우리는 깊은 소스 스레드를 볼 필요가 :
public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
init(group, target, name, stackSize);
}
复制代码
우리는 다른 건축 방법의 일부이기 때문에, 가장 복잡한 시공 방법 중 하나를 선택, 우리가 진정으로 초기화 init 메소드에서 수행된다, 실제로 init 메소드를 호출 여기에서 볼 수 있습니다. 우리는뿐만 아니라 표정으로 갈 수 있습니다
private void init(ThreadGroup g, Runnable target, String name,long stackSize) {
init(g, target, name, stackSize, null, true);
}
复制代码
초기화 방법은 하나이지만 파라미터 중 두 개 이상 존재한다. 밖으로 우리가 가서보고 얘기를해야 찾으려면 :
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
//第一部分:确保线程名字不为空
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
//第二部分:指定线程组
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
if (security != null) {
g = security.getThreadGroup();
}
if (g == null) {
g = parent.getThreadGroup();
}
}
g.checkAccess();
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
this.group = g;
//第三部分:一些其他参数设置
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
//第四部分:runnable接口配置
this.target = target;
setPriority(priority);
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
//第五部分:设置栈大小
this.stackSize = stackSize;
//第六部分:设置线程ID
tid = nextThreadID();
}
复制代码
마지막으로 우리는 스레드를 초기화 할 수있는 방법을 발견했다. 우리는 다섯 개 부분으로 나누어 :
(1) 부 : 스레드 이름은 비워 둘 수 없습니다,
개발자가 스레드의 이름을 지정하는 표시하지 않는 경우 여기에 하나의 스레드의 이름을 언급 할 것, 자바 관계자는 우리에게 물었다 스레드는 "스레드 -"는 thread의 이름으로 구성된 디지털 접미사 접두사가 될 것입니다. 그러나 어떤 경우에도 우리는 스레드 이름이 필요합니다.
(2) 파트 II : 현재 스레드의 스레드 그룹을 지정합니다
코드 내부 g가 비어 있지 않은 경우, 우리는 그렇지 않으면 스레드 그룹의 상위 클래스를 사용, 스레드 그룹 g 현재의 thread로 이것을 사용하고 있는지, 매우 분명하다. 물론, 중간에뿐만 아니라 등등 권한 문제 등을 확인한다.
(3) 제 III 부 : 기타 구성
다음은 구성이 너무 스레드, 우선 순위, 클래스 로더 및 데몬에 설정되어 있습니다.
(4) 제 IV : 실행 가능한 인터페이스 구성
지정은 실행 가능한 인터페이스 클래스를 구현합니다.
(5) 제 V는 : 스택의 크기를 설정합니다
스레드 스택의 크기는 인수 제로 전송 프로세스의 기본 크기 스레드 스택 즉 기본 크기에 따라 알 수있다
(6) 제 VI : 쓰레드 ID를 설정
스레드 ID가 nextThreadID 방법으로 특정된다. 우리는 스레드 ID를 지정하는 방법을 볼 수 있습니다.
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
复制代码
우리는 사실, threadSeqNumber을 볼 수 있습니다.
OK, 위의 나는 우리가 아주 명확하다 생각 스레드를 초기화하는 방법이며,이 생성자 초기화 방법의 다른 매개 변수는 단지 몇 가지 변경했습니다. 하지만 원리는 동일합니다. 이전 기사에서 언급 한 문제는 아직 읽어 해결되지 않았습니다.
라고 셋째, 왜 시작 방법은 스레드를 시작할 수 있습니다
이 문제를 해결하기 위해 우리는 또한 깊이 (jdk1.8)의 소스 코드를보고있다 :
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
}
}
}
复制代码
이 코드는 무엇을 의미합니까? 먼저 스레드 상태가 비정상 여부를 결정합니다, 현재 스레드가 스레드 마지막 호출을 시작하는 시작 start0 공식적인 방법 전에 스레드 그룹에 추가됩니다. 이제 열쇠는 여기에, 우리는뿐만 아니라 모양을 잡기에 갈 수도 start0 방법이 정말 시작 스레드입니다 :
즉, 시작하는 기본 방법의 진정한 시작이다, 실행 방법은 그것의 내용 안에 실행 왜 메서드 호출이 실행되지 것 같다. 공식 문서는 설명 그렇게되어 JNI 메소드가 내부 실행 start0 메소드를 호출합니다. 이러한 문장은 위의 이유를 설명하는 것입니다.
이미이 문제를 해결, 제 생성자이며, 우리가 시작 방법은 실행보다는 스레드를 시작할 수 있습니다 부르는 이유 두 번째는 이해합니다. 우리는 API 메소드가 실질적으로 모든 네이티브 스레드를 제공, 소스 코드를 알 수 분석 할 수 있습니다.