안녕하세요 활짝웃자입니다.

Java / HTML5 / CSS / JSP / Spring / DataBase : Postgresql / Apache Tomcat을 모두 사용하게 되어서

기본 문법만 하고 프로그래밍 했었는데 필요하게 된 부분들이 많아져서 글을 작성하게 되었습니다.

 

이것이 자바다 교재를 사용하여 진행하였습니다.

총 2권으로 나누어져 있는데, 1권은 기본 문법 + Java에서 자주 사용되는 API등을 다루는 내용입니다.

2권은 멀티스레드, 제네릭, 람다식, 컬렉션 프레임워크, 스트림과 병렬 처리, 네티워킹 등 기본 문법을 숙지 후, 개발 업무 시 자주 사용되는 부분을 설명하는 내용입니다.

 

Java 게시글은 다음과 같은 방식으로 진행 됩니다.

1. 이것이 자바다 교재가 아니어도 Java 기본 문법을 알고 계신다고 생각하며 진행합니다.

2. 모든 내용을 다루지는 않을 것이며 참고한 부분은 분명하게 출처를 밝히면서 진행합니다.

 

 

 

멀티태스킹두 가지 이상의 작업을 동시에 처리하는 것입니다.

이때 사용되는 방법 중 하나인 멀티 스레드가 있습니다.

멀티스레드에서 동기화, 비동기화의 개념이 존재 하는데 해당 개념은 다음의 출처를 통해 확인해 주시기 바랍니다.

 

Synchronous(동기) vs Asynchronous(비동기)

 

Synchronous(동기) Vs Asynchronous(비동기)

 

nesoy.github.io

동기화를 실험해 보기 위해 비동기를 먼저 확인해 보도록 합시다.

 

 

Calculator.java - 공유객체

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package thread_synchronized;
 
public class Calculator {
 
    private int memory;
    
    public int getMemory() {
        return memory;
    }
    
    public  void setMemory(int memory) {
        this.memory = memory;
        try {
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName() + ": " + this.memory);
        } catch(InterruptedException e) {
            /* 이것이 자바다 교재에서는 이 부분(catch)으로 실행이 되는 것 같지만
             * 제가 실행할 때는 정상적으로 출력이 되지 않아서
             * try 부분에 확인을 위한 코드를 삽입 하였습니다.
             */
            System.out.println(Thread.currentThread().getName() + ": " + this.memory);
        }
    }
}
 

 

 

User1.java - User1 스레드

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package thread_synchronized;
 
public class User1 extends Thread {
 
    private Calculator calculator;
    
    public void setCalculator(Calculator calculator) {
        this.setName("User1");
        this.calculator = calculator;
    }
    
    public void run() {
        calculator.setMemory(100);
    }
}
 

 

 

User2.java - User2 스레드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package thread_synchronized;
 
public class User2 extends Thread {
 
    private Calculator calculator;
    
    public void setCalculator(Calculator calculator) {
        this.setName("User2");
        this.calculator = calculator;
    }
    
    public void run() {
        calculator.setMemory(50);
    }
}
 

 

 

MainThreadExample.java - 메인 스레드가 실행하는 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package thread_synchronized;
 
public class MainThreadExample {
 
    public static void main(String[] args) {
        Calculator calculator = new Calculator();
        
        User1 user1 = new User1();
        user1.setCalculator(calculator);
        user1.start();
        
        User2 user2 = new User2();
        user2.setCalculator(calculator);
        user2.start();
    }
}

 

MainThreadExample.java를 실행하면 다음과 같은 결과를 확인 하실 수 있습니다.

 

User1: 50

User2: 50

 

위와 같이 동시에 실행하는 것만 생각하고, 공유가 되면 안 되는 부분을 해결하기 위해 synchronized를 사용합니다.

 

MainThreadExample, User1, User2는 동일하므로 Calculator만 수정합니다.

 

 

수정된 Calculator.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package thread_synchronized;
 
public class Calculator {
 
    private int memory;
    
    public int getMemory() {
        return memory;
    }
    
    public synchronized void setMemory(int memory) {
        this.memory = memory;
        try {
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName() + ": " + this.memory);
        } catch(InterruptedException e) {
            /* 이것이 자바다 교재에서는 이 부분(catch)으로 실행이 되는 것 같지만
             * 제가 실행할 때는 정상적으로 출력이 되지 않아서
             * try 부분에 확인을 위한 코드를 삽입 하였습니다.
             */
            System.out.println(Thread.currentThread().getName() + ": " + this.memory);
        }
    }
}
 

 

Calculator.java를 위와 같이 수정해 주시고, 실행하시면 다음과 같이

 

User1: 100

User2: 50

 

동시에 실행을 하지만 공유가 되지 않은 결과가 출력되는 것을 확인하실 수 있습니다.

 

 

소개해드린 예제는 이것이 자바다에 있습니다!

동시에 실행은 해야 하지만 공유가 되면 안 되는 동기화 프로그래밍을 해야 되는 경우가 의외로 많습니다.

 

제가 진행했던 개인 프로젝트 중 Java를 사용한 간단한 Hash비교 기능과 랜섬웨어에 의하여 암호화된 파일들을 복호화 해주는 백신 아닌 백신을 제작하였었는데, 당시 빠른검사, 정밀검사 기능을 제작하던 중, GUI에서 Progress Bar를 사용하여 검사 중인 파일의 경로 + 파일명, 진행상태 표시를 위한 Progress Bar 를 실행하니 실시간으로 진행되는 파일명 출력과 게이지가 차지를 않고, 검사 종료 후, 맨 마지막에 검사한 파일의 파일명만 출력되고, 게이지 또한 공백 상태에서 꽉찬 게이지 형식으로 변경이 되었었습니다.

 

당시 pannel thread와 검사 thread 간의 임계영역 간섭 문제였던걸로 생각이 들어서 검사 thread에 synchronized를 적용하니 정상적으로 일반 백신처럼 진행되는 것을 확인 할 수 있었습니다.

 

모든 상황이 저와 같지는 않으시겠지만 굉장히 다양한 경우가 많으니 검색등을 통하여 알아보시기 바랍니다!

 

 

+ Recent posts