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 메소드 위쪽에 스택으로 쌓이게 되며, 병행 처리를 하지 못하게 됩니다.
::멀티 쓰레드 정적 할당을 통해 소수 판별
/*쓰레드별로 판단할 소수를 분할해주는 방법
* 정적 로드밸런싱을 통한 소수 판별
* 쓰레드 갯수를 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);
}
}
}
결과
윈도우 운영체제 확인
- 키보드의 (Windows) 키를 누른 상태에서 R 키를 입력합니다. 또는 시작 => 실행을 차례대로 클릭합니다.
- 빈 필드에 "winver"를 입력합니다. 그런 다음 확인을 클릭합니다.
- Windows의 버전을 확인합니다. 이것이 사용 중인 운영 체제(OS)입니다.
'CS > Java' 카테고리의 다른 글
[Java] 자바 입문 강의 텍스트 정리 (0) | 2021.10.15 |
---|---|
[Java] A JNI error has occurred 에러 해결 방법 (0) | 2021.05.25 |
[Java] java 와 javac 버전 차이날 때 해결하는 방법 (4) | 2021.05.24 |
[Java] java, javac 명령어로 컴파일하고 실행하는 방법 (0) | 2021.05.23 |
[Java] 자바 정적, 동적 쓰레드 할당 및 분석(소수 계산) (0) | 2021.05.09 |