쓰레드를 여러개 놓고 이들을 동시에 실행하려면 우선 다음과 같은 절차를 밟으면 되는줄 알고 다음과 같은 방법으로 테스트를 해보기로 하였습니다.
1. 쓰레드 몇개 생성
테스트를 위해 더하기, 빼기, 곱하기, 나누기 등을 반복적으로 하는 쓰레드를 다음과 같이 생성해 보았습니다.
(1) Add.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 | public class Add extends Thread { @Override public void run() { for(int i=0; i<100; i++) { // Val 클래스의 val이라는 정적 변수에 1 더합니다. Val.val++; // 그리고 변한 값을 콘솔에 보여줍니다. System.out.println("Value after addition: " + Val.val); try { // sleep메소드는 일정 시간 동안 메소드의 실행을 일시적으로 중지합니다. // 여기서 인자는 1000분의 1초값이므로 0.1초는 100이 됩니다. Thread.sleep(100); } catch(InterruptedException e) { e.printStackTrace(); } } } } | cs |
(2) Subtract.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class Subtract implements Runnable { @Override public void run() { for(int i=0; i<100; i++) { Val.val--; System.out.println("Value after subtract: " + Val.val); try { Thread.sleep(110); } catch(InterruptedException e) { e.printStackTrace(); } } } } | cs |
(3) Multiply.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class Multiply implements Runnable { @Override public void run() { for(int i=0; i<50; i++) { Val.val = Val.val * 1.1; System.out.println("Value after multiplication: " + Val.val); try { Thread.sleep(200); } catch(InterruptedException e) { e.printStackTrace(); } } } } | cs |
(4) Division.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class Division implements Runnable { @Override public void run() { for(int i=0; i<50; i++) { Val.val = Val.val / 1.2; System.out.println("Value after division: " + Val.val); try { Thread.sleep(220); } catch(InterruptedException e) { e.printStackTrace(); } } } } | cs |
2. 공유할 값을 갖는 클래스 생성
1 2 3 4 5 | public class Val { public static double val = 0.0; } | cs |
3. 마지막으로 위의 소스코드를 테스트 하기 위해 메인메소드를 갖는 클래스를 만들었습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class ThreadTest { public static void main(String args[]) { Add add = new Add(); Subtract subtract = new Subtract(); Multiply multiply = new Multiply(); Division division = new Division(); add.start(); subtract.run(); multiply.run(); division.run(); } } | cs |
이렇게 해서 실행을 해봤는데, 기대하기로는 각 쓰레드가 반복하면서 공유하는 값을 각자 가진 연산기능을 수행하여 변경할줄 알았습니다. 그런데 막상 코드를 실행해 보니, 더하기와 빼기 쓰레드 만이 동시에 실행이 되었고, 이들 쓰레드가 종료된 다음에야 곱하기 쓰레드가 실행되고 그다음에 마지막으로 나누기 쓰레드가 실행이 되었습니다.
기존에 원했던 동시 실행을 하기 위해서 이래저래 조사를 해본 결과, 원하던 바를 구현하기 위해서는 ExecutorService와 Executor라는 클래스를 활용하여야 한다는 것을 알았습니다. 이 두 클래스는 java.util.concurrent 패키지 소속으로, 동시 프로그래밍 (concurrent programming) 구현을 위해 존재하는 라이브러리인 것입니다.
ExecutorService 클래스는 동시에 실행하고자 하는 쓰레드를 하나의 쓰레드풀로 묶어서 실행할 수 있게 해주며, 따라서 위의 메인메소드를 다음과 같이 수정해 보도록 하겠습니다. 위의 네가지 쓰레드를 하나의 풀로 묶기 위해 ExecutorService의 인스턴스를 생성하고, 거기에 포함시키기 위해 submit() 메소드를 호출하여 각 쓰레드를 담습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadTest { public static void main(String args[]) { Add add = new Add(); Subtract subtract = new Subtract(); Multiply multiply = new Multiply(); Division division = new Division(); ExecutorService exs = Executors.newFixedThreadPool(4); exs.submit(add); exs.submit(subtract); exs.submit(multiply); exs.submit(division); } } | cs |
submit() 호출 후 별도의 start()나 run() 메소드를 호출하지 않습니다. 이대로 실행해보면 초반에 의도했던대로 쓰레드가 동시에 실행되는 것을 확인할 수 있습니다.
'Java > 스레드' 카테고리의 다른 글
[자바] Thread (1) - Thread는 무엇인가? (0) | 2017.04.21 |
---|