(2) 스 레 드 의 응용 및 도전
지난 글 에서 우 리 는 프로 세 스 와 스 레 드 의 발전 역사, 스 레 드 의 생명 주기, 스 레 드 의 장점 과 사용 장면 을 이해 했다. 이 편 은 자바 차원 에서 스 레 드 의 사용 을 더욱 잘 알 게 되 었 다.
콘 텐 츠 탐색
다 중 스 레 드 를 도입 하 는 목적 은 첫 번 째 편 에서 언급 한 바 와 같이 CPU 를 충분히 이용 하기 위해 프로그램 이 더 빨리 실행 되 는 것 이다. 물론 시작 하 는 스 레 드 가 많 을 수록 좋다 는 것 은 아니다.실제 다 중 스 레 드 를 사용 할 때 매우 많은 도전 에 직면 하 게 된다.
스 레 드 보안 문제
스 레 드 보안 문제 값 은 여러 스 레 드 가 같은 대상 에 접근 할 때 이러한 운행 환경 에서 사용 하 는 스 케 쥴 링 방식 이나 이런 스 레 드 가 어떻게 교체 되 는 지 고려 하지 않 으 면 코드 에서 동기 화 작업 이 필요 없 는 상황 에서 이런 유형 은 정확 한 행 위 를 나 타 낼 수 있다.그러면 이 종 류 는 스 레 드 가 안전 한 것 입 니 다. 예 를 들 어 아래 의 코드 는 하나의 사례 모델 입 니 다. 코드 의 주석 에서 여러 스 레 드 가 동시에 방문 하면 여러 개의 인 스 턴 스 가 나타 납 니 다.단 례 의 효 과 를 실현 할 수 없 게 하 다
public class SingletonDemo {
private static SingletonDemo singletonDemo=null;
private SingletonDemo(){}
public static SingletonDemo getInstance(){
if(singletonDemo==null){/*** ***/
singletonDemo=new SingletonDemo();
}
return singletonDemo;
}
}
일반적으로 우 리 는 다 중 스 레 드 프로 그래 밍 중의 스 레 드 안전 문 제 를 다음 과 같은 세 가지 로 분류 하고 모든 문제 의 본질 에 대해 후속 적 인 글 에서 우 리 는 단독으로 설명 할 것 이다.
단일 핵심 CPU 구조 에서 다 중 스 레 드 의 운행 은 CPU 시간 편 전환 을 바탕 으로 하 는 의사 병렬 입 니 다.시간 이 매우 짧 기 때문에 사용 자 는 여러 스 레 드 가 병행 되 는 줄 알 았 다.한 번 의 컨 텍스트 전환 은 실제 적 으로 현재 스 레 드 가 시간 편 을 실행 한 후에 다른 스 레 드 로 전환 하고 현재 스 레 드 가 실 행 된 상 태 를 저장 하 는 과정 입 니 다.컨 텍스트 전환 은 스 레 드 의 실행 속도 에 영향 을 주 고 시스템 에 있어 서 대량의 CPU 시간 을 소모 한 다 는 것 을 의미 합 니 다.
컨 텍스트 전환 줄 이기
스 레 드 안전 문 제 를 해결 하 는 장면 에서 우 리 는 자 물 쇠 를 사용 하 는 것 을 비교적 많이 고려 할 것 이다. 왜냐하면 그것 은 사용 이 비교적 간단 하기 때문이다.그러나 자물쇠 의 사용 이 적당 하지 않 으 면 자물쇠 가 잠 길 가능성 을 초래 할 수 있다. 자물쇠 가 잠 겨 있 으 면 비교적 심각 한 문제 가 발생 할 수 있다. 자물쇠 가 생 긴 스 레 드 는 자물쇠 자원 을 계속 점용 하고 다른 자 물 쇠 를 가 져 오 려 는 스 레 드 도 잠 겨 서 시스템 이 붕 괴 될 수 있다.
다음은 자물쇠 가 잠 긴 간단 한 사례 입 니 다.
public class DeadLockDemo {
//
private final Object lockA = new Object();
private final Object lockB = new Object();
private void deadLock(){
new Thread(()->{
synchronized (lockA){
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lockB){
System.out.println("Lock B");
}
}
}).start();
new Thread(()->{
synchronized (lockB){
synchronized (lockA){
System.out.println("Lock A");
}
}
}).start();
}
public static void main(String[] args) {
new DeadLockDemo().deadLock();
}
}
jstack 를 통 해 잠 금 분석
1. 우선 jps 를 통 해 현재 실행 중인 프로 세 스 의 pid 가 져 오기
6628 Jps
17588 RemoteMavenServer
19220 Launcher
19004 DeadLockDemo
2. jstack 스 택 정 보 를 인쇄 하고 jstack 19004 를 입력 하면 다음 로 그 를 인쇄 합 니 다. 잠 금 된 정보 알림 을 뚜렷하게 볼 수 있 습 니 다.
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x000000001d461e68 (object 0x000000076b310df8, a java.lang.Object),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x000000001d463258 (object 0x000000076b310e08, a java.lang.Object),
which is held by "Thread-1"
자물쇠 해결 수단
1. 여러 스 레 드 가 같은 순서 로 자 물 쇠 를 가 져 올 수 있 도록 합 니 다.
2. 자 물 쇠 를 가 져 오 는 시간 초과 설정, 설정 시간 초과 후 자동 방출
3. 잠 금 검사
자원 제한
자원 제한 은 주로 하드웨어 자원 과 소프트웨어 자원 을 말 하 는데 다 중 스 레 드 응용 을 개발 할 때 프로그램의 실행 속 도 는 이 두 자원 에 제한 을 받는다.하드웨어 의 자원 제한 은 디스크, CPU, 메모리, 네트워크 가 아 닙 니 다.소프트웨어 자원 의 제한 이 매우 많다. 예 를 들 어 데이터베이스 연결 수, 컴퓨터 가 지원 할 수 있 는 최대 연결 수 등 자원 제한 으로 인 한 문제 의 가장 직관 적 인 표현 은 바로 앞에서 말 한 문맥 전환 이다. 즉, CPU 자원 과 스 레 드 자원 의 심각 한 불 균형 으로 인해 빈번 한 문맥 전환 이 발생 하고 오히려 프로그램의 운행 속도 가 떨 어 질 수 있다.
자원 제한의 주요 해결 방안 은 부족 한 것 을 보충 하 는 것 이다.CPU 가 부족 하면 CPU 핵심 수 를 증가 시 킬 수 있 습 니 다.한 대의 기계 의 자원 이 유한 하면 여러 대의 기 계 를 증가 시 켜 군집 을 만든다.
자바 에서 스 레 드 사용
자바 에서 다 중 스 레 드 를 실현 하 는 방식 은 비교적 간단 하 다. 자바 에서 매우 편리 한 API 를 제공 하여 다 중 스 레 드 를 실현 하기 때문이다.1. Thread 클래스 를 계승 하여 다 중 스 레 드 실현 2. Runnable 인터페이스 실현 3. Callable 인터페이스 가 Future 포장 기 를 통 해 Thread 스 레 드 를 만 드 는 것 을 실현 합 니 다. 이것 은 반환 값 이 있 는 스 레 드 입 니 다. 4. 스 레 드 탱크 ExecutorService 를 사용 합 니 다.
Thread 클래스 계승
Thread 클래스 를 계승 하고 run 방법 을 다시 쓰 십시오. run 방법 에서 현재 스 레 드 가 실행 해 야 할 논 리 를 작성 합 니 다.마지막 으로 스 레 드 인 스 턴 스 start 방법 으로 스 레 드 를 시작 합 니 다.
public class ThreadDemo extends Thread{
@Override
public void run() {
// run ,
System.out.println("Hello world");
}
public static void main(String[] args) {
ThreadDemo threadDemo=new ThreadDemo();
threadDemo.start();
}
}
Thread 클래스 는 Runnable 인 터 페 이 스 를 실 현 했 기 때문에 Thread 자신 도 하나의 스 레 드 인 스 턴 스 입 니 다. 그러나 우 리 는 new Thread (). start () 로 스 레 드 를 시작 할 수 없습니다. 이 유 는 간단 합 니 다. Thread 클래스 의 run 방법 은 실제 적 인 의미 가 없습니다. 구조 함 수 를 통 해 보 내 온 다른 Runnable 실현 클래스 를 호출 하 는 run 방법 일 뿐 입 니 다.이 구체 적 인 프레젠테이션 은 Runnable 인터페이스 코드 에서 볼 수 있 습 니 다.
public
class Thread implements Runnable {
/* What will be run. */
private Runnable target;
...
@Override
public void run() {
if (target != null) {
target.run();
}
}
...
Runnable 인터페이스 구현
스 레 드 를 사용 해 야 하 는 클래스 가 다른 클래스 를 계승 했다 면 자바 의 단일 계승 원칙 에 따라 Thread 류 를 계승 하여 스 레 드 를 실현 할 수 없 기 때문에 Runnable 인 터 페 이 스 를 실현 하여 다 중 스 레 드 를 실현 할 수 있 습 니 다.
public class RunnableDemo implements Runnable{
@Override
public void run() {
// run ,
System.out.println("Hello world");
}
public static void main(String[] args) {
RunnableDemo runnableDemo=new RunnableDemo();
new Thread(runnableDemo).start();
}
}
위의 코드 에서 Runnable 인 터 페 이 스 를 실현 하고 run 방법 을 다시 썼 습 니 다.이 어 Runnable Demo 라 는 스 레 드 를 시작 하기 위해 서 는 Thread 류 를 예화 해 야 합 니 다. 구조 적 방법 으로 Runnable 인터페이스 실현 류 를 전달 하여 시작 해 야 합 니 다. Thread 의 run 방법 은 target. run 을 호출 하여 현재 스 레 드 를 실행 하고 코드 는 위 에 있 습 니 다.
Callable 인터페이스 구현
일부 다 중 스 레 드 가 사용 하 는 장면 에서 우 리 는 가끔 비동기 스 레 드 가 실 행 된 후의 피드백 결 과 를 얻어 야 한다. 아마도 메 인 스 레 드 는 하위 스 레 드 의 실행 결 과 를 얻어 다른 업무 논 리 를 처리 해 야 할 것 이다. 아마도 스 레 드 가 실 행 된 상 태 를 알 아야 할 것 이다.그러면 Callable 인 터 페 이 스 는 이 기능 을 잘 실현 할 수 있 습 니 다.
public class CallableDemo implements Callable{
@Override
public String call() throws Exception {
return "hello world";
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable callable=new CallableDemo();
FutureTask task=new FutureTask<>(callable);
new Thread(task).start();
System.out.println(task.get());//
}
}
위의 코드 사례 에서 마지막 줄 task. get () 은 스 레 드 의 반환 값 을 가 져 오 는 것 입 니 다. 이 과정 은 막 혔 습 니 다. 하위 스 레 드 가 실행 되 지 않 았 을 때 메 인 스 레 드 는 결과 가 돌아 올 때 까지 계속 막 힙 니 다.
스 레 드 풀 사용
자주 스 레 드 를 만 들 고 스 레 드 를 없 애 는 성능 비용 을 줄 이기 위해 실제 사용 할 때 우 리 는 스 레 드 탱크 로 스 레 드 를 만 들 것 입 니 다. 여기 서 저 는 다 중 스 레 드 의 장점 과 원 리 를 전개 하지 않 고 후속 적 인 글 에서 따로 설명 하 겠 습 니 다.
public class ExecutorServiceDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//
ExecutorService pool = Executors.newFixedThreadPool(1);
Future future=pool.submit(new CallableDemo());
System.out.println(future.get());
}
}
pool. submit 는 반환 값 이 있 는 스 레 드 인 스 턴 스 를 전달 할 수 있 고 반환 값 이 없 는 스 레 드 인 스 턴 스 를 전달 할 수 있 습 니 다. 소스 코드 는 다음 과 같 습 니 다.
/*01*/Future> submit(Runnable task);
/*02*/ Future submit(Runnable task, T result);
/*03*/ Future submit(Callable task);
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JAVA 다 중 스 레 드 메커니즘 의 스 레 드 생 성target 을 실행 대상 으로 지정 한 name 을 이름 으로 하고 group 에서 참조 하 는 스 레 드 그룹의 일원 으로 새 Thread 대상 을 할당 합 니 다. 이 스 레 드 가 독립 된 Runnable 실...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.