반응형

intellij 환경에서 시행

 

::메인 함수 만들기

프로젝트를 만들고  Main 클래스를 작성한다.

작성 후 psvm 입력 후 자동완성하면 

public static void main(String[] args) {

}

이 생성된다.

 

::싱글 쓰레드로 소수를 판별하기 위한 주어진 함수 작성

//코드 단순화 및 소수판별함수 최적화가 가능하지만 일단 주어진 코드 해석이 먼저이기에 주석을 달아놨다.

//싱글 쓰레드에서 소수가 몇 개가 되는지 알아보기 위한 클래스

public class pc_serial {
    //20만까지 테스트하기 위함
    private static final int NUM_END = 200000;
    
    //메인함수
    public static void main(String[] args) {
        //소수의 수를 저장하기 위한 counter
        int counter=0;
        //for 문에서 소수를 테스트하기 위한 변수
        int i;
        //시작 시간을 측정하기 위한 변수
        long startTime = System.currentTimeMillis();
        //소수인지 테스트
        for (i = 0; i<NUM_END; i++ ){
            //소수이면 counter에 1을 더한다.
            if (isPrime(i)) counter++;
        }
        //끝나는 시간을 측정하기 위한 변수
        long endTime = System.currentTimeMillis();
        //실제 실행 시간이 얼마인지를 측정하기 위한 변수
        long timeDiff = endTime - startTime;
        //실행 시간 출력문
        System.out.println("Execution Time : "+ timeDiff+"ms");
        //1부터 NUM_END-1까지의 소수의 갯수 출력문
        System.out.println("1..."+(NUM_END-1)+" prime# counter=" + counter +"\n");

    }

    //소수 판별 함수. 판별하기 위한 숫자를 x로 받는다.
    private static boolean isPrime(int x){
        //임시 변수 i 설정
        int i;
        //받은 숫자가 1이라면 false 반환
        if (x<=1) return false;
        //i를 2부터 x-1까지 실행한다. 
        for (i=2;i<x;i++){
            //만약 x가 i로 나누어지고(% 연산 시 0 출력) i가 x가 아니라면 소수가 아니니 false 반환
            //사실 여기는 코드를 단순화 가능
            if(((x%i)==0)&&(i!=x)) return false;
        }
        return true;
    }

}

 

::인텔리제이에서 코드 실행하는 방법

1. 프로젝트 빌드 단축키 :: Ctrl+F9(오른쪽 위 망치 모양)

Add Configuration에서 실행할 환경 셋팅 후 실행

 

2. 실행하고자 하는 클래스에서 오른쪽 마우스를 누른 후 run 버튼을  누른다.

 

::자바 쓰레드의 실행법?

스레드를 시작할 때에는 구현한 run() 메서드를 시작하는게 아닌, start()메서드를 시작해야 정상적으로 실행시킬 수 있습니다.

스레드를 run() 메서드를 통해 실행시킨다면, 스레드는 main 메소드 위쪽에 스택으로 쌓이게 되며, 병행 처리를 하지 못하게 됩니다.

출처:deveric.tistory.com/21

 

::멀티 쓰레드 정적 할당을 통해 소수 판별

/*쓰레드별로 판단할 소수를 분할해주는 방법
 * 정적 로드밸런싱을 통한 소수 판별
 * 쓰레드 갯수를 NUM_THREAD로 미리 정해준다.
 *
 * 단순하게 1~NUM_END까지를 NUM_THREAD로 나눠주면 쓰레드별로 부하가 크게 차이난다.
 * ex.1~800까지일 때 [1,100],...,[700,800]에서 [700,800]이 부하가 훨씬 크다.
 * 그렇기에 1~NUM_END을 적절하게 나누어 쓰레드마다 받을 부하를 비슷하게 해준다.
 *
 * 가장 간단하게 하는 방법? 쓰레드별로 쓰레드 각각의 번호부터 NUM_THREAD 만큼씩 더한 값을 판별한다.
 * ex. NUM_THREAD = 2? [1, 3, 5, 7, ..., 1+2n, ...], [2, 4, 6, 8, ..., 2+2n, ...]
 * 장점? 분할이 효과적으로 된다.
 * 단점? 이또한 제대로 분할이 되지 않는다. 짝수를 담당하는 쓰레드는 훨씬 빨리 끝난다.
 *
 * 단점해결?
 * 짝수는 계산하지 않는다. 다만 짝수 2를 카운트하기 위해 미리 1 추가
 * [1, 5, 9, ..., n + 2*NUM_THREAD], [3, 7, 11, ..., n + 2*NUM_THREAD]
 * 로 해준다.
 * serial도 동일하게 해주기 위해 짝수만 계산하자.
 * */

public class pc_static {
    // 20만까지 테스트하기 위함
    private static final int NUM_END = 200000;
    private static final int NUM_THREAD = 2;

    // 메인함수
    public static void main(String[] args) throws InterruptedException {
        // 소수의 수를 저장하기 위한 counter. 짝수 2를 카운트하기 위해 미리 1 추가
        thread_static.counter = 1;
        // for 문에서 소수를 테스트하기 위한 변수
        int i;

        // 쓰레드 생성 및 변수 할당
        thread_static[] thread = new thread_static[NUM_THREAD];
        // 쓰레드에 시작값 할당
        for (int t = 0; t < NUM_THREAD; t++) {
            // 배열은 0부터 시작이라 0에는 1을, 1에는 3을 할당하기 위해 1 추가.
            thread[t] = new thread_static(1 + t * 2);
        }

        //시작 시간을 측정하기 위한 변수
        long startTime = System.currentTimeMillis();
        // 소수인지 테스트
        // 쓰레드 시작
        for (int t = 0; t < NUM_THREAD; t++) {
            thread[t].start();
        }
        // 시간 측정을 위해 join 을 이용해 쓰레드가 끝날 때까지 대기
        for (int t = 0; t < NUM_THREAD; t++) {
            thread[t].join();
        }

        // 끝나는 시간을 측정하기 위한 변수
        long endTime = System.currentTimeMillis();
        // 실제 실행 시간이 얼마인지를 측정하기 위한 변수
        long timeDiff = endTime - startTime;

        // (1) execution time of each thread
        // 쓰레드별 실행 시간 출력문
        for (int t = 0; t < NUM_THREAD; t++) {
            System.out.println("Thread-" + t + "'s Execution Time : " + thread[t].timeDiff + "ms");
        }

        // (2) execution time when using all threads
        // 전체 실행 시간 출력문
        System.out.println("Execution Time : " + timeDiff + "ms");

        // 1부터 NUM_END-1까지의 소수의 갯수 출력문
        System.out.println("1..." + (NUM_END - 1) + " prime# counter=" + thread_static.counter + "\n");

    }

    // 소수 판별 함수. 판별하기 위한 숫자를 x로 받는다.
    private static boolean isPrime(int x) {
        // 임시 변수 i 설정
        int i;
        // 받은 숫자가 1이라면 false 반환
        if (x <= 1) return false;
        // i를 2부터 x-1까지 실행한다.
        for (i = 2; i < x; i++) {
            // 만약 x가 i로 나누어지고(% 연산 시 0 출력) i가 x가 아니라면 소수가 아니니 false 반환
            // 사실 여기는 코드를 단순화 가능
            if (((x % i) == 0) && (i != x)) return false;
        }
        return true;
    }

    static class thread_static extends Thread {
        // 쓰레드에서 처음 판단할 숫자를 변수 x로 주었다.
        int x;
        // 소수 숫자를 세기 위해 counter 변수를 클래스 내에 선언해줬다.
        static int counter;
        // 쓰레드 끝난 후 더하기 위해 임시 변수 선언
        int temp = 0;
        // 쓰레드 시작 시간
        long startTime;
        // 쓰레드 종료 시간
        long endTime;
        // 쓰레드 실행 시간
        long timeDiff;

        // constructor, 생성자로 변수 전달
        public thread_static(int x) {
            this.x = x;
        }

        public void run() {
            // 쓰레드 시작 시간
            startTime = System.currentTimeMillis();

            // 소수 판별용 변수 i
            int i;
            // x :: 처음 판단할 숫자
            // i<NUM_END :: i부터 NUM_END-1 까지
            // i = i+NUM_THREAD :: i부터 판단할 숫자는 NUM_THREAD 씩 더한다.
            for (i = x; i < NUM_END; i = i + NUM_THREAD * 2) {
                // 소수이면 temp 에 1을 더한다.
                if (isPrime(i)) temp++;
            }

            // 클래스 내 counter 변수에 소수를 더한다.
            counter += temp;
            // 쓰레드 종료 시간
            endTime = System.currentTimeMillis();
            // 쓰레드 실행 시간
            timeDiff = endTime - startTime;
        }
    }
}

싱글 쓰레드 코드도 바꿔주었다.

홀수들만 계산할 수 있도록. 소수 2를 계산에 넣어주기 위해 카운트 변수를 1부터 시작

//싱글 쓰레드에서 소수가 몇 개가 되는지 알아보기 위한 클래스

public class pc_serial {
    //20만까지 테스트하기 위함
    private static final int NUM_END = 200000;

    //메인함수
    public static void main(String[] args) {
        //소수의 수를 저장하기 위한 counter. 짝수 2를 카운트하기 위해 미리 1 추가
        int counter=1;
        //for 문에서 소수를 테스트하기 위한 변수
        int i;
        //시작 시간을 측정하기 위한 변수
        long startTime = System.currentTimeMillis();
        //소수인지 테스트. 1부터 시작
        for (i = 1; i<NUM_END; i = i+2 ){
            //소수이면 counter에 1을 더한다.
            if (isPrime(i)) counter++;
        }
        //끝나는 시간을 측정하기 위한 변수
        long endTime = System.currentTimeMillis();
        //실제 실행 시간이 얼마인지를 측정하기 위한 변수
        long timeDiff = endTime - startTime;
        //실행 시간 출력문
        System.out.println("Execution Time : "+ timeDiff+"ms");
        //1부터 NUM_END-1까지의 소수의 갯수 출력문
        System.out.println("1..."+(NUM_END-1)+" prime# counter=" + counter +"\n");

    }

    //소수 판별 함수. 판별하기 위한 숫자를 x로 받는다.
    private static boolean isPrime(int x){
        //임시 변수 i 설정
        int i;
        //받은 숫자가 1이라면 false 반환
        if (x<=1) return false;
        //i를 2부터 x-1까지 실행한다.
        for (i=2;i<x;i++){
            //만약 x가 i로 나누어지고(% 연산 시 0 출력) i가 x가 아니라면 소수가 아니니 false 반환
            //사실 여기는 코드를 단순화 가능
            if(((x%i)==0)&&(i!=x)) return false;
        }
        return true;
    }

}

 

인텔리제이(IntelliJ) 자동 정렬 설정(단축키)

IntelliJ에서 Ctrl + Alt + L 을 누르면, 자동 정렬을 해준다.

 

 

::멀티 쓰레드 동적 할당을 통해 소수 판별

/*쓰레드별로 판단할 소수를 분할해주는 방법
 * 동적 로드밸런싱을 통한 소수 판별
 *
 * 1~NUM_THREAD 까지 isPrime 변수를 1부터 2씩 추가해간다.
 * 이때 isPrime 변수를 synchronized 를 사용하여 충돌하지 않도록 업데이트 해준다.
 *
 * 쓰레드 갯수를 NUM_THREAD 로 미리 정해준다.
 *
 *
 * */

public class pc_dynamic {
    // 20만까지 테스트하기 위함
    private static final int NUM_END = 200000;
    private static final int NUM_THREAD = 16;

    // 메인함수
    public static void main(String[] args) throws InterruptedException {
        // 소수의 수를 저장하기 위한 counter. 짝수 2를 카운트하기 위해 미리 1 추가
        thread_dynamic.counter = 1;
        // for 문에서 소수를 테스트하기 위한 변수
        int i;

        // 쓰레드 생성
        thread_dynamic[] thread = new thread_dynamic[NUM_THREAD];
        // 쓰레드에 시작값 할당
        // isPrime 는  처음 할당된 값들 이후부터 계산할 것이다.
        for (int t = 0; t < NUM_THREAD; t++) {
            // 배열은 0부터 시작이라 0에는 1을, 1에는 3을 할당하기 위해 1 추가.
            thread[t] = new thread_dynamic(1 + t * 2);
        }
        // 판단을 시작할 변수를 할당해줬다.
        thread_dynamic.isPrime = NUM_THREAD * 2 - 1;

        //시작 시간을 측정하기 위한 변수
        long startTime = System.currentTimeMillis();
        // 소수인지 테스트
        // 쓰레드 시작
        for (int t = 0; t < NUM_THREAD; t++) {
            thread[t].start();
        }
        // 시간 측정을 위해 join 을 이용해 쓰레드가 끝날 때까지 대기
        for (int t = 0; t < NUM_THREAD; t++) {
            thread[t].join();
        }

        // 끝나는 시간을 측정하기 위한 변수
        long endTime = System.currentTimeMillis();
        // 실제 실행 시간이 얼마인지를 측정하기 위한 변수
        long timeDiff = endTime - startTime;

        // (1) execution time of each thread
        // 쓰레드별 실행 시간 출력문
        for (int t = 0; t < NUM_THREAD; t++) {
            System.out.println("Thread-" + t + "'s Execution Time : " + thread[t].timeDiff + "ms");
        }

        // (2) execution time when using all threads
        // 전체 실행 시간 출력문
        System.out.println("Execution Time : " + timeDiff + "ms");

        // 1부터 NUM_END-1까지의 소수의 갯수 출력문
        System.out.println("1..." + (NUM_END - 1) + " prime# counter=" + thread_dynamic.counter + "\n");

    }

    // 소수 판별 함수. 판별하기 위한 숫자를 x로 받는다.
    private static boolean isPrime(int x) {
        // 임시 변수 i 설정
        int i;
        // 받은 숫자가 1이라면 false 반환
        if (x <= 1) return false;
        // i를 2부터 x-1까지 실행한다.
        for (i = 2; i < x; i++) {
            // 만약 x가 i로 나누어지고(% 연산 시 0 출력) i가 x가 아니라면 소수가 아니니 false 반환
            // 사실 여기는 코드를 단순화 가능
            if (((x % i) == 0) && (i != x)) return false;
        }
        return true;
    }

    static class thread_dynamic extends Thread {
        // 쓰레드에서 처음 판단할 숫자를 변수 x로 주었다.
        //  isPrime 에서 x를 할당 받아올 것이다.
        int x;
        // 소수 숫자를 세기 위해 counter 변수를 클래스 내에 선언해줬다.
        static int counter;
        // 소수인지 확인할 변수를 변수를 클래스 내에 선언해줬다.
        static int isPrime;
        // 쓰레드 끝난 후 더하기 위해 임시 변수 선언
        int temp = 0;
        // 쓰레드 시작 시간
        long startTime;
        // 쓰레드 종료 시간
        long endTime;
        // 쓰레드 실행 시간
        long timeDiff;

        public thread_dynamic(int x) {
            this.x = x;
        }

        public void run() {
            // 쓰레드 시작 시간
            startTime = System.currentTimeMillis();

            // isPrime 는 판단할 변수를 의미하는데 이것이 NUM_END 를 넘어가면 종료하도록 했다.
            while (isPrime < NUM_END) {
                {
                    if (isPrime(this.x)) temp++;
                    //순서 중요하다. 할당된 것을 계산하고 업데이트해줘야 한다.
                    this.x = update();
                }
            }

            // 클래스 내 counter 변수에 소수를 더한다.
            counter += temp;

            // 쓰레드 종료 시간
            endTime = System.currentTimeMillis();
            // 쓰레드 실행 시간
            timeDiff = endTime - startTime;
        }

        //여기를 synchronized 로 해줬다. x 를 isPrime 에서 가져오고 isPrime 는 2 더해준다.
        static synchronized int update() {
            isPrime = isPrime + 2;
            return isPrime;
        }
    }
}

 

 

정적 쓰레드 실행 결과

 

 

동적 쓰레드 실행 결과

 

 

행렬

import java.util.*;
import java.lang.*;

// command-line execution example) java MatmultD 6 < mat500.txt
// 6 means the number of threads to use
// < mat500.txt means the file that contains two matrices is given as standard input
//
// In eclipse, set the argument value and file input by using the menu [Run]->[Run Configurations]->{[Arguments], [Common->Input File]}.

// Original JAVA source code: http://stackoverflow.com/questions/21547462/how-to-multiply-2-dimensional-arrays-matrix-multiplication

public class MatmultD {
    private static Scanner sc = new Scanner(System.in);

    public static void main(String[] args) throws InterruptedException {
        int thread_no = 0;
        if (args.length == 1) thread_no = Integer.valueOf(args[0]);
        else thread_no = 1;

        //변수 초기화
        thread_matrix.answer = 0;

        int a[][] = readMatrix();
        int b[][] = readMatrix();

        long startTime = System.currentTimeMillis();

        //쓰레드 생성
        thread_matrix[] thread = new thread_matrix[thread_no];
        for (int t = 0; t < thread_no; t++) {
            thread[t] = new thread_matrix(t, thread_no, a, b);
        }

        //쓰레드 실행
        for (int t = 0; t < thread_no; t++) {
            thread[t].start();
        }

        //쓰레드 마칠 때까지 대기
        for (int t = 0; t < thread_no; t++) {
            thread[t].join();
        }

        long endTime = System.currentTimeMillis();

        // 쓰레드별 실행 시간 출력문
        for (int t = 0; t < thread_no; t++) {
            System.out.println("Thread-" + t + "'s Execution Time : " + thread[t].timeDiff + "ms");
        }
        System.out.printf("[thread_no]:%2d , [Time]:%4d ms\n", thread_no, endTime - startTime);

        // 쓰레드별 실행 시간 출력문
        for (int t = 0; t < thread_no; t++) {
            System.out.println("Thread-" + t + "'s Sum : " + thread[t].temp );
        }

        System.out.println("Matrix Sum = " + thread_matrix.answer + "\n");

    }

    public static int[][] readMatrix() {
        int rows = sc.nextInt();
        int cols = sc.nextInt();
        int[][] result = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                result[i][j] = sc.nextInt();
            }
        }
        return result;
    }

    public static void printMatrix(int[][] mat) {
        System.out.println("Matrix[" + mat.length + "][" + mat[0].length + "]");
        int rows = mat.length;
        int columns = mat[0].length;
        int sum = 0;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < columns; j++) {
                System.out.printf("%4d ", mat[i][j]);
                sum += mat[i][j];
            }
            System.out.println();
        }
        System.out.println();
        System.out.println("Matrix Sum = " + sum + "\n");
    }


    static class thread_matrix extends Thread {
        // 쓰레드에서 처음 계산할 행의 숫자를 start, 다음 연산행은 core 로 주었다.
        int start;
        int core;
        int[][] a;
        int[][] b;

        // 행렬곱의 최종합을 구하기 위해 answer 변수를 클래스 내에 선언해주었다.
        static int answer;

        // 쓰레드 끝난 후 더하기 위해 임시 변수 선언
        int temp = 0;

        // n = a의 열의 길이. a[0]행의 원소의 갯수이다.
        int n;
        // m = a의 행의 길이
        int m;
        // p = b의 열의 길이. b[0]행의 원소의 갯수이다.
        int p;
        //int[][] ans = new int[m][p];

        // 쓰레드 시작 시간
        long startTime;
        // 쓰레드 종료 시간
        long endTime;
        // 쓰레드 실행 시간
        long timeDiff;

        // constructor, 생성자로 변수 전달
        public thread_matrix(int start, int core, int[][] a, int[][] b) {
            this.start = start;
            this.core = core;
            this.a = a;
            this.b = b;
        }

        public void run() {
            // 쓰레드 시작 시간
            startTime = System.currentTimeMillis();

            // n = a의 열의 길이. a[0]행의 원소의 갯수이다.
            n = a[0].length;
            // m = a의 행의 길이
            m = a.length;
            // p = b의 열의 길이. b[0]행의 원소의 갯수이다.
            p = b[0].length;
            //int[][] ans = new int[m][p];

            // a의 행의 길이까지
            for (int i = start; i < m; i = i + core) {
                // b의 열의 길이까지
                for (int j = 0; j < p; j++) {
                    // a의 열의 길이까지
                    for (int k = 0; k < n; k++) {
                        // 행렬 식 계산
                        temp += a[i][k] * b[k][j];
                    }
                }
            }
            answer = answer + temp;

            // 쓰레드 종료 시간
            endTime = System.currentTimeMillis();
            // 쓰레드 실행 시간
            timeDiff = endTime - startTime;
            //System.out.println("start = " + start);

        }
    }
}

 

결과

 

윈도우 운영체제 확인

  1. 키보드의 (Windows) 키를 누른 상태에서 R 키를 입력합니다. 또는 시작 => 실행을 차례대로 클릭합니다.
  2. 빈 필드에 "winver"를 입력합니다. 그런 다음 확인을 클릭합니다.
  3. Windows의 버전을 확인합니다. 이것이 사용 중인 운영 체제(OS)입니다.
반응형

+ Recent posts