Java 스레드에서 시작 메소드와 실행 메소드를 사용하는 방법
start 메소드 및 실행 메소드
$start()$ 메소드는 스레드를 시작하는 데 사용됩니다. 이때 스레드는 ready(실행 가능) 상태이며 $cpu가 실행되지 않습니다. $ 시간 조각을 얻었습니다. $run()$ 메서드 실행을 시작합니다. $run()$ 메소드를 직접 호출하는 것은 본질적으로 현재 스레드에서 실행되는 클래스의 메소드만 호출하므로 $start()$ 메소드를 사용하여 $run()$를 호출해야만 달성할 수 있습니다. 방법. 진정한 멀티스레딩.
샘플 코드
@Slf4j(topic = "c.Test4") public class Test4 { public static void main(String[] args) { Thread t1 = new Thread("t1"){ @Override public void run() { log.debug("running"); } }; t1.run(); } }
위 코드는 직접 호출되는 $run()$ 메소드입니다. $main$ 스레드가 이 메서드를 실행했다는 인쇄된 정보를 볼 수 있습니다.
@Slf4j(topic = "c.Test4") public class Test4 { public static void main(String[] args) { Thread t1 = new Thread("t1"){ @Override public void run() { log.debug("running"); } }; t1.start(); } }
그리고 $start()$ 메소드를 사용하여 시작하면 $t1$ 스레드에 의해 실행되는 실제 $run$ 메소드입니다.
Note
$Thread$ 객체가 $start()$ 메서드를 호출하면 준비 상태로 들어가므로 $start()$ 메서드를 호출할 수 없습니다. 그렇지 않으면 다음 코드에 표시된 대로 $IllegalThreadStateException$ 예외가 발생합니다.
@Slf4j(topic = "c.Test4") public class Test4 { public static void main(String[] args) { Thread t1 = new Thread("t1"){ @Override public void run() { log.debug("running"); } }; t1.start(); t1.start(); } }
예외 정보:
sleep 메서드 및 생성 메서드
sleep
$sleep()$ 메서드를 호출하면 현재 스레드가 $Running$ 상태에서 $Time Waiting$ 상태로 변경됩니다(차단됨)
다른 스레드는 $interrupt$ 메서드를 사용하여 잠자는 스레드를 중단할 수 있습니다. 이때 $sleep$ 메서드는 throw InterruptedException
슬리핑 후 스레드가 즉시 실행되지 않을 수 있습니다
더 나은 가독성을 얻으려면 $Thread$의 $sleep$ 대신 $TimeUnit$의 $sleep$을 사용하는 것이 좋습니다. 샘플 코드
@Slf4j(topic = "c.Test5") public class Test5 { public static void main(String[] args) { Thread t1 = new Thread("t1"){ @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }; t1.start(); log.debug("t1 state {}", t1.getState()); //让主线程休眠500ms try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } log.debug("t1 state {}", t1.getState()); } } //17:13:21.729 [main] DEBUG c.Test5 - t1 state RUNNABLE //17:13:22.245 [main] DEBUG c.Test5 - t1 state TIMED_WAITING
위 코드에서는 $t1$ 스레드가 먼저 시작되는데, 이때 인쇄 스레드의 상태는 $RUNNABLE$ 상태여야 하며, 메인 스레드를 sleep 상태로 두면 메인 스레드가 인쇄를 먼저 실행하지 못하게 됩니다. , 그러나 아직 $sleep()$ 상태에 들어가지 않았습니다. $run()$의 $sleep$ 메소드가 실행되면 스레드는 $TIMED WAITING$ 상태가 됩니다
@Slf4j(topic = "c.Test6") public class Thread6 { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread("t1") { @Override public void run() { try { log.debug("enter sleep"); Thread.sleep(2000); } catch (InterruptedException e) { log.debug("wake up"); e.printStackTrace(); } } }; t1.start(); Thread.sleep(1000); log.debug("interrupt t1"); //被唤醒 t1.interrupt(); } }
실행 결과
위 코드에서 $start$ 메소드가 시작되면, $t1$ 스레드는 슬립 상태에 들어가고 프롬프트 정보를 인쇄하며 슬립 시간은 $2s$입니다. $main$ 스레드에서 $1s$를 슬립한 후 $t1$ 스레드의 슬립을 중단하고 중단 메시지를 표시합니다. 정보를 확인하고 $interrupt()$ 메서드를 호출합니다. 이 시점에서 스레드가 중단되고 예외가 발생합니다.
$TimeUnit$ 클래스에는 더 읽기 쉬운 새로운 단위가 추가되었지만 본질적으로 차이는 없습니다. 이는 단지 단위 변환일 뿐입니다
TimeUnit.SECONDS.sleep(1);//该语句作用是睡眠一秒
yield
$yield$를 호출하면 현재 프로세스 $Running$에서 $Runnable$ 준비 상태로 들어간 후 다른 스레드를 예약하고 실행합니다. 구체적인 구현은 운영 체제의 작업 스케줄러에 따라 다릅니다(즉, 작업 스케줄러에 다른 작업이 없는 경우에도 마찬가지입니다. $cpu$를 포기하면 스레드를 계속 실행합니다.) $sleep$은 실행 후 차단 상태로 들어갑니다. 이때 sleep 시간이 끝나지 않으면 $cpu$는 스레드에 할당되지 않습니다. $yield$는 준비 상태로 들어갑니다. 즉, 다른 스레드를 실행할 필요가 없으면 스레드에도 시간 조각이 할당됩니다. 이는 $sleep$과 $yield$ 스레드 우선순위
Thread의 가장 큰 차이점입니다. 우선 순위
는 스케줄러에게 스레드 예약의 우선 순위를 지정하라는 메시지를 표시하지만 이는 단지 메시지일 뿐이므로 스케줄러는 무시할 수 있습니다.
$cpu$가 사용 중인 경우 우선 순위가 더 높은 항목이 더 많은 시간 조각을 얻지만 $cpu $가 유휴 상태이면 우선 순위가 거의 존재하지 않습니다
Sleep 응용 프로그램 - CPU가 100%를 차지하는 것을 방지
without $cpu$를 사용하여 계산할 때 $while(true)$를 유휴 상태로 두지 말고 $cpu를 낭비하세요. $. 이때 $yield$ 또는 $sleep$을 사용하여 $cpu$ 사용을 다른 프로그램에 넘길 수 있습니다
while (true) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } }
예 $wait$ 또는 조건 변수를 사용하면 유사한 효과를 얻을 수 있습니다
차이점은 후자입니다. 두 개는 잠금 및 해당 깨우기 작업이 필요하며 일반적으로 동기화가 필요한 시나리오에 적합합니다
$sleep$는 잠금 동기화가 필요하지 않은 시나리오에 적합합니다
join 방법
다음 프로그램의 인쇄 결과:
@Slf4j(topic = "c.Test6") public class Test6 { static int r = 0; public static void main(String[] args) { test(); } private static void test() { log.debug("开始"); Thread t = new Thread("t1") { @Override public void run() { log.debug("开始"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } log.debug("结束"); r = 10; } }; t.start(); log.debug("r的值是{}", r); log.debug("结束"); } }
메인 스레드와 $t1$ 스레드가 병렬이므로 $t1$ 스레드는 $r$ 값을 계산하려면 $1s$가 필요하며, 메인 스레드는 $r$ 값을 다음과 같이 인쇄합니다. 시작이므로 인쇄된 값은 0
입니다. 해결 방법:
Can인 $t.start();$ 뒤에 $t.join();$을 추가합니다. $join$의 기능은 스레드 실행이 완료될 때까지 기다리는 것입니다.
호출자 입장에서 실행을 계속하기 전에 결과가 반환될 때까지 기다려야 한다면 동기식이고, 실행을 계속하기 위해 반환 결과를 기다릴 필요가 없다면 비동기식입니다.
그래서 $join$ 메소드는 실제로 동기식으로 실행되도록 허용합니다.
유효한 대기가 있습니다.
$join(milliseconds)$ 메소드는 스레드 실행 시간이 짧은 경우 대기 시간에 전달할 매개변수를 가질 수 있습니다. 대기 시간보다 크면 대기 시간이 지나면 대기가 중지됩니다. 스레드 실행 시간이 대기 시간보다 작으면 스레드 실행이 완료된 후 대기가 종료됩니다. 설정된 대기 시간은 만료되지 않습니다.
interrupt方法
打断$sleep, wait, join$的线程,即打断阻塞状态的线程
打断$sleep$的线程,会清空打断状态
@Slf4j(topic = "c.Test7") public class Test7 { public static void main(String[] args) throws InterruptedException { Thread t = new Thread("t1"){ @Override public void run() { log.debug("sleep..."); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } }; t.start(); Thread.sleep(1000); log.debug("interrupt"); t.interrupt(); log.debug("打断标记: {}", t.isInterrupted()); } }
打断正常运行的线程,不会清空打断状态
因此我们可以在线程中判断打断标记,来决定是否被打断,以及执行被打断之前的收尾工作。
@Slf4j(topic = "c.Test8") public class Test8 { public static void main(String[] args) throws InterruptedException { Thread t = new Thread("t1"){ @Override public void run() { while (true) { if (Thread.currentThread().isInterrupted()) { log.debug("线程被打断了"); break; } } } }; t.start(); Thread.sleep(1000); log.debug("interrupt"); t.interrupt(); } }
守护线程
默认情况下,$java$需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其他非守护线程运行结束了,即使守护线程的代码没有执行完毕,也会强制结束。
@Slf4j(topic = "c.Test10") public class Test10 { public static void main(String[] args) throws InterruptedException { Thread t = new Thread("t1") { @Override public void run() { while (true) { } } }; //设置线程为守护线程 t.setDaemon(true); t.start(); Thread.sleep(1000); log.debug("主线程结束"); } }
如果不把$t$设置为守护线程,则因为线程内部的死循环,导致程序不会结束运行。
위 내용은 Java 스레드에서 시작 메소드와 실행 메소드를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Java의 난수 생성기 안내. 여기서는 예제를 통해 Java의 함수와 예제를 통해 두 가지 다른 생성기에 대해 설명합니다.

Java의 Weka 가이드. 여기에서는 소개, weka java 사용 방법, 플랫폼 유형 및 장점을 예제와 함께 설명합니다.

Java의 Smith Number 가이드. 여기서는 정의, Java에서 스미스 번호를 확인하는 방법에 대해 논의합니다. 코드 구현의 예.

이 기사에서는 가장 많이 묻는 Java Spring 면접 질문과 자세한 답변을 보관했습니다. 그래야 면접에 합격할 수 있습니다.

Java 8은 스트림 API를 소개하여 데이터 컬렉션을 처리하는 강력하고 표현적인 방법을 제공합니다. 그러나 스트림을 사용할 때 일반적인 질문은 다음과 같은 것입니다. 기존 루프는 조기 중단 또는 반환을 허용하지만 스트림의 Foreach 메소드는이 방법을 직접 지원하지 않습니다. 이 기사는 이유를 설명하고 스트림 처리 시스템에서 조기 종료를 구현하기위한 대체 방법을 탐색합니다. 추가 읽기 : Java Stream API 개선 스트림 foreach를 이해하십시오 Foreach 메소드는 스트림의 각 요소에서 하나의 작업을 수행하는 터미널 작동입니다. 디자인 의도입니다

Java의 TimeStamp to Date 안내. 여기서는 소개와 예제와 함께 Java에서 타임스탬프를 날짜로 변환하는 방법에 대해서도 설명합니다.

캡슐은 3 차원 기하학적 그림이며, 양쪽 끝에 실린더와 반구로 구성됩니다. 캡슐의 부피는 실린더의 부피와 양쪽 끝에 반구의 부피를 첨가하여 계산할 수 있습니다. 이 튜토리얼은 다른 방법을 사용하여 Java에서 주어진 캡슐의 부피를 계산하는 방법에 대해 논의합니다. 캡슐 볼륨 공식 캡슐 볼륨에 대한 공식은 다음과 같습니다. 캡슐 부피 = 원통형 볼륨 2 반구 볼륨 안에, R : 반구의 반경. H : 실린더의 높이 (반구 제외). 예 1 입력하다 반경 = 5 단위 높이 = 10 단위 산출 볼륨 = 1570.8 입방 단위 설명하다 공식을 사용하여 볼륨 계산 : 부피 = π × r2 × h (4
