자바 가 병발 하 는 몇 가지 방식 의 소결 을 실현 하 다

10163 단어 Java병발 하 다
자바 병발 을 실현 하 는 몇 가지 방법
자바 프로그램 은 기본적으로 단일 스 레 드 로 실 행 됩 니 다.
synchronized
자바 는 synchronized 키 워드 를 사용 하여 한 번 에 하나의 스 레 드 만 코드 블록 을 실행 할 수 있 도록 보장 합 니 다.

public synchronized void code() {
    // TODO
}
Volatile
Volatile 키 워드 는 모든 스 레 드 가 Volatile 수식 변 수 를 읽 을 때 이 변수의 최신 데 이 터 를 읽 도록 합 니 다.
Threads 와 Runnable.

public class MyRunnable implements Runnable {
    @Override
    public void run() {
     // TODO
    }
}

import java.util.ArrayList;
import java.util.List;
public class Main {
    public static void main(String[] args) {
        Runnable task = new MyRunnable();
        Thread worker = new Thread(task);
        worker.setName('Myrunnable');
        worker.start();
}
thread 를 만 들 면 overhead 가 많 고 성능 이 낮 으 며 관리 가 쉽 지 않 습 니 다.
Thread pools

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
    private static final int NUMOFTHREDS = 5;
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(NUMOFTHREDS);
        for (int i = 0; i < 50; i++) {
            Runnable worker = new MyRunnable(i);
            executor.execute(worker);
        }
        // executor     threads
        executor.shutdown();
        //     threads  
        executor.awaitTermination();
        System.out.println("Finished all threads");
    }
}
Futures 와 Callables
Runnable 대상 이 호출 자 에 게 결 과 를 되 돌 릴 수 없 기 때문에,우 리 는 Callable 클래스 로 결 과 를 되 돌 릴 수 있 습 니 다.

package de.vogella.concurrency.callables;
import java.util.concurrent.Callable;
public class MyCallable implements Callable<Long> {
    @Override
    public Long call() throws Exception {
  // TODO
  int sum = 1;
        return sum;
    }
}

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CallableFutures {
    private static final int NUMOFTHREDS = 5;
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(NUMOFTHREDS);
        List<Future<Long>> list = new ArrayList<Future<Long>>();
        for (int i = 0; i < 10; i++) {
            Callable<Long> worker = new MyCallable();
            Future<Long> submit = executor.submit(worker);
            list.add(submit);
        }
        long sum = 0;
        for (Future<Long> future : list) {
            try {
                sum += future.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        System.out.println(sum);
        executor.shutdown();
    }
}
CompletableFuture
Complete bleFuture 는 Future 를 바탕 으로 비동기 호출 기능 을 추가 했다.callback()함수 Thread 실행 이 끝 날 때 자동 으로 호출 됩 니 다.
Complete ableFuture 는 차단 도 지원 하고 차단 되 지 않 은 callback()도 지원 합 니 다.

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureSimpleSnippet {
    public static void main(String[] args) { 
        CompletableFuture<Integer>  data = createCompletableFuture()
                .thenApply((Integer count) -> {
                    int transformedValue = count * 10;
                    return transformedValue;
                });
            try {
              int count = futureCount.get();
             } catch (InterruptedException | ExecutionException ex) {
            }
    }
    private static CompletableFuture<Integer> createCompletableFuture() {
        CompletableFuture<Integer> futureCount = CompletableFuture.supplyAsync(
                () -> {
                    return 1;
                });
        return futureCount;
    }
}
자바
동시성 과 동기 화 를 잘 이해 하기 위해 서 는 먼저 두 가지 중요 한 개념 을 알 아야 한다.동기 화 와 비동기 이다.
동기 화 란 함수 나 방법 을 실행 한 후에 시스템 이 값 이나 메 시 지 를 되 돌려 주 기 를 기다 리 는 것 으로 이해 할 수 있 습 니 다.이 때 프로그램 은 막 혀 서 되 돌아 오 는 값 이나 메 시 지 를 받 은 후에 만 다른 명령 을 수행 합 니 다.동기 화 는 한 가지 일,한 가지 일,한 가지 일 을 하 는 것 이다.
비동기,함수 나 방법 을 실행 한 후 반환 값 이나 메 시 지 를 차단 하지 않 고 시스템 에 비동기 과정 을 의뢰 하면 시스템 이 반환 값 이나 메 시 지 를 받 을 때 시스템 은 의뢰 의 비동기 과정 을 자동 으로 촉발 하여 완전한 절 차 를 완성 합 니 다.이 보 는 한 가지 일 을 하 는 것 이 다른 일 을 하 는 데 영향 을 주지 않 는 다 는 것 이다.
동기 화 키워드 synchronized.이 동기 화 감시 대상 이 클래스 라면 한 대상 이 클래스 에 있 는 동기 화 방법 을 방문 하면 다른 대상 이 클래스 에 있 는 이 동기 화 방법 을 계속 방문 하려 면 차단 에 들 어 갑 니 다.이전 대상 이 이 동기 화 방법 을 실행 한 후에 야 현재 대상 이 이 방법 을 계속 수행 할 수 있 습 니 다.이것 이 바로 동기 화 다.반면 방법 전에 동기 화 키워드 수식 이 없 으 면 서로 다른 대상 이 같은 시간 에 같은 방법 에 접근 할 수 있다 는 것 이 비동기 다.
더러 운 데이터:한 업무 가 데 이 터 를 방문 하고 데 이 터 를 수정 하 는 것 을 말 합 니 다.이런 수정 은 데이터 베이스 에 제출 되 지 않 았 습 니 다.이때 다른 업무 도 이 데 이 터 를 방문 한 다음 에 이 데 이 터 를 사 용 했 습 니 다.이 데 이 터 는 아직 제출 되 지 않 은 데이터 이기 때문에 다른 사무 에서 읽 은 이 데 이 터 는 더러 운 데이터(Dirty Data)로 더러 운 데이터 에 따라 작 동 하 는 것 이 정확 하지 않 을 수 있 습 니 다.
1.병발 문제 가 무엇 입 니까?
여러 프로 세 스 나 스 레 드 가 같은 자원 에 동시에 접근 하면 문제 가 발생 할 수 있 습 니 다.
예 를 들 어 A,B 운용 자 는 1 잔액 이 1 천원 인 계 좌 를 동시에 읽 고 A 운용 자 는 이 계 좌 를 위해 100 원 을 추가 하 며 B 운용 자 는 동시에 이 계 좌 를 위해 50 원 을 빼 고 A 는 먼저 제출 하고 B 는 나중에 제출한다.마지막 으로 실제 계좌 잔액 은 1000-50=950 위안 이지 만 1000+100-50=1050 이 어야 한다.이것 이 바로 전형 적 인 병발 문제 다.어떻게 해결 합 니까?
동시 다발 과 동기 화 문 제 를 처리 하 는 것 은 주로 잠 금 체 제 를 통 해 이 루어 진다.
2.동시 다발 과 동기 화 를 어떻게 처리 합 니까?
하 나 는 자바 의 동기 잠 금 입 니 다.전형 적 인 것 은 동기 키워드 synchronized 입 니 다.
또 다른 전형 적 인 것 은 비관 적 인 자물쇠 와 낙관적 인 자물쇠 다.
자바 에 서 는 원자 성 조작(즉 동기 화 작업)을 실현 하 는 두 가지 방식 이 있 습 니 다.
1)동기 화 키 워드 를 사용 하여 synchronized
2)lock 잠 금 체 제 를 사용 하 는 데 도 해당 하 는 읽 기와 쓰기 자물쇠 가 포함 된다.
비관 적 인 자 물 쇠 는 그 이름 처럼 데이터 가 외부(본 시스템 의 현재 다른 사무,그리고 외부 시스템 에서 온 사무 처리 포함)에 의 해 수정 되 는 것 에 대해 보수 적 인 태 도 를 가지 기 때문에 전체 데이터 처리 과정 에서 데 이 터 를 잠 금 상태 에 두 는 것 을 말한다.
낙관적 인 잠 금 은 대부분 데이터 버 전 Version)기록 체 제 를 바탕 으로 이 루어 진다.데이터 버 전 이란 무엇 입 니까?즉,데이터 에 버 전 표 지 를 추가 하 는 것 이다.데이터 베 이 스 를 바탕 으로 하 는 버 전 솔 루 션 에서 보통 데이터 베 이 스 를 위 한'version'필드 를 추가 하여 이 루어 진다.데 이 터 를 읽 고 꺼 낼 때 이 버 전 번 호 를 함께 읽 고 업데이트 할 때 이 버 전 번 호 를 1 로 추가 합 니 다.이때 제출 한 데이터 의 버 전 데 이 터 를 데이터베이스 테이블 에 대응 하 는 기 록 된 현재 버 전 정보 와 비교 하고 제출 한 데이터 버 전 번호 가 데이터베이스 테이블 의 현재 버 전 번호 보다 크 면 업데이트 한다.그렇지 않 으 면 만 료 된 데이터 라 고 생각한다.
낙관적 인 잠 금 체 제 는 우리 시스템 에서 이 루어 진 것 으로 외부 시스템 에서 온 사용자 잔액 업데이트 작업 은 우리 시스템 의 통 제 를 받 지 않 기 때문에 더러 운 데이터 가 데이터 베이스 에 업 데 이 트 될 수 있 습 니 다.시스템 디자인 단계 에서 우 리 는 이러한 상황 이 발생 할 가능성 을 충분히 고려 하고 해당 하 는 조정 을 해 야 한다(예 를 들 어 낙관적 인 잠 금 전략 을 데이터 베이스 저장 과정 에서 실현 하고 대외 적 으로 이 저장 과정 을 바탕 으로 하 는 데이터 업데이트 경 로 를 개방 해 야 한다).
[조심 하 세 요.면접 관 이 자물쇠 에 관 한 질문 을 합 니 다!!!자물쇠 가 잠 겨 있 는 문제 에 대해 서 는 나머지 한 블 로그 에 설명 이 있 습 니 다.]
3.흔히 볼 수 있 는 동시 다발 사례 분석
사례 1.예매 시스템 사례
어떤 비행 기 는 비행기표 한 장 밖 에 없다.만약 에 1w 사람 이 당신 의 사 이 트 를 열 어 표를 예매 한다 고 가정 하면 병발 문 제 를 어떻게 해결 하 는 지 물 어 볼 것 이다.
만약 에 우리 가 동기 화 체제 나 데이터 베이스 물리 잠 금 체 제 를 사용 했다 고 가정 하면 1w 개인 이 표를 동시에 볼 수 있 도록 어떻게 보장 하 는 지 성능 을 희생 할 것 이 고 높 은 병행 사이트 에서 바람 직 하지 않다.
낙관적 인 자 물 쇠 를 채택 하면 이 문 제 를 해결 할 수 있다.낙관적 인 자 물 쇠 는 표를 잠 그 지 않 은 상황 에서 업무 의 통 제 를 이용 하여 병발 문 제 를 해결 하 는 것 을 의미한다.즉,데이터 의 병발 가 독성 을 확보 하고 데 이 터 를 저장 하 는 배타성 을 확보 하 며 성능 을 확보 하 는 동시에 병발 로 인 한 더러 운 데이터 문 제 를 해결 하 는 것 이다.
어떻게 낙관적 인 자 물 쇠 를 실현 합 니까?
전제:기 존 표 에 불필요 한 필드,version 버 전 번호,long 형식 을 추가 합 니 다.
원리:
1)현재 버 전 번호>=데이터베이스 시트 버 전 번호 만 제출 가능
2)제출 성공 후 버 전 번호 version+
사례 2.주식 거래 시스템,은행 시스템,빅 데이터 양 을 어떻게 생각 하 십 니까?
우선,주식 거래 시스템 의 시세 표 는 몇 초 에 한 개의 시세 기록 이 발생 하고 하루 에 한 개의 주식 수량 이 있다.×20×60*6 개의 기록,1 월 에 내 려 오 면 이 표 의 기록 수량 은 얼마 입 니까?한 장의 표 의 기록 수가 100 w 를 넘 으 면 조회 성능 이 매우 떨 어 지 는데,어떻게 시스템 성능 을 보증 합 니까?
그리고 예 를 들 어 중국 이동 에 억 대의 사용자 가 있 는데 시 계 는 어떻게 디자인 합 니까?모든 것 을 시계 에 저장 합 니까?
따라서 대량의 시스템 은 표 분할 을 고려 해 야 합 니 다.-(표 이름 은 다 르 지만 구 조 는 똑 같 습 니 다)통용 되 는 몇 가지 방식:(상황 에 따라 정 합 니 다)
1)업무 에 따라 핸드폰 번호 의 시계 와 같이 우 리 는 130 으로 시작 하 는 것 을 하나의 시계 로 고려 할 수 있다.131 로 시작 하 는 다른 시 계 는 이런 식 으로 유추 할 수 있다.
2)표 분할 메커니즘 을 이용 하여 표 작성
3)거래 시스템 이 라면 우 리 는 시간 축 에 따라 나 누 어 당일 데이터 시트,역사 데 이 터 를 다른 표 로 구 하 는 것 을 고려 할 수 있다.이곳 의 역사 데이터 의 보고서 와 조 회 는 당일 거래 에 영향 을 주지 않 을 것 이다.
그 밖 에 우 리 는 캐 시 를 고려 해 야 한다.
이곳 의 캐 시 는 응용 에 독립 되 어 있 으 며,여전히 메모리 의 읽 기 입 니 다.만약 우리 가 데이터 베 이 스 를 자주 방문 하 는 것 을 줄 일 수 있다 면 시스템 에 큰 유리 할 것 입 니 다.예 를 들 어 전자상거래 시스템 의 상품 검색,만약 에 어떤 키워드 의 상품 이 자주 검색 된다 면 이 부분의 상품 목록 을 캐 시(메모리 에 저장)에 저장 하 는 것 을 고려 할 수 있다.이렇게 하면 매번 데이터 베 이 스 를 방문 하지 않 아 도 성능 이 크게 증가한다.
4.흔히 볼 수 있 는 높 은 방문 효율 을 향상 시 키 는 수단
우선 높 은 병발 의 병목 이 어디 에 있 는 지 알 아야 한다.
1.서버 네트워크 대역 폭 이 부족 한 것 같 습 니 다.
2.웹 스 레 드 연결 이 부족 할 수 있 습 니 다.
3.데이터베이스 연결 조회 가 올 라 가지 않 을 수 있 습 니 다.
상황 에 따라 해결 방향 도 다르다.
1.첫 번 째 상황 처럼 네트워크 대역 폭 을 증가 시 킬 수 있 고 DNS 도 메 인 이름 은 여러 대의 서버 를 분석 하여 배포 할 수 있 습 니 다.
2.부하 균형,프 록 시 nginx,apache 등
3.데이터베이스 조회 최적화,읽 기와 쓰기 분리,표 나 누 기 등
마지막 으로 높 은 병발 아래 에서 자주 처리 해 야 할 내용 을 복사 합 니 다.
1.사용자 캐 시,정보 캐 시 등 을 포함 하여 캐 시 를 사용 하고 메모리 로 캐 시 를 하면 데이터 베이스 와 의 상호작용 을 대량으로 줄 이 고 성능 을 향상 시 킬 수 있 습 니 다.
2.jproleer 등 도구 로 성능 병목 을 찾아내 추가 비용 을 줄인다.
3.데이터베이스 조회 문 구 를 최적화 하고 hibenate 등 도 구 를 직접 사용 하 는 직접 생 성 문 구 를 줄인다(시간 이 비교적 긴 조회 만 최적화).
4.데이터베이스 구 조 를 최적화 하고 색인 을 많이 만들어 조회 효율 을 높 인 다.
5.통계 의 기능 은 가능 한 한 캐 시 를 하거나 매일 통계 또는 정시 에 관련 보고 서 를 통계 하여 필요 할 때 통계 하 는 기능 을 피한다.
6.정적 페이지 를 사용 할 수 있 는 곳 은 가능 한 한 사용 하고 용기 의 해석 을 감소 합 니 다(동적 내용 을 정적 html 로 생 성하 여 표시 합 니 다).
7.상기 문 제 를 해결 한 후에 서버 클 러 스 터 를 이용 하여 한 대의 병목 문 제 를 해결 합 니 다.
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.

좋은 웹페이지 즐겨찾기