Sio's Programming
스레드 (Runnable,Thread, synchronized) 본문
스레드란?
아마도 한 번쯤은 멀티 프로세스라는 말을 들어 본 적이 있을 겁니다. 멀티 프로세스란 컴퓨터가 여러 가지 일을 동시에 하고 있는 것을 뜻합니다.
지금 저의 경우 컴퓨터에서 음악이 나오고, 워드프로그램을 사용하고, 동료한테 무거운 파일을 전송해 주고 있습니다. 이것이 멀티프로세스 입니다.
그럼 스레드(멀티스레드)란 무엇일까요? 위에서 말한 하나의 프로세스에서 다시 여러 가지 일을 하는 것을 뜻 합니다. 예를 들어 파일을 전송하면서 채팅을 하고 있습니다. 동일한 채팅프로그램에서 파일전송과 채팅을 동시에 하고 있는 것 입니다.
채팅 프로그램 프로세스 -> 파일전송 스레드
-> 채팅 스레드
JAVA는 기본적으로 멀티스레드를 지원 하고 있습니다.
스레드는 두 가지 형태로 존재 합니다. 하나는 객체 하나를 n개의 스레드가 공유 하는 방식 이고, 또 다른 하나는 객체 하나당 하나의 스레드가 존재하는 방식 입니다.
객체0 -> 스레드0 객체0 - 스레드0
-> 스레드1 객체1 - 스레드1
-> 스레드2 객체2 - 스레드2
Runnable 인터페이스 구현을 통한 Thread
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package com.javalec.ex; public class MainClass { public static void main(String[] args) { ThreadTest threadTest = new ThreadTest(); Thread thread = new Thread(threadTest, "A"); thread.start(); System.out.println(Thread.currentThread().getName()); //main thread에 이름을 출력함 //스레드는 따로 행동하기 때문에 위에 start로 Ruunable을 실행하더라도 신경쓰지않고 따로 실행을함 } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package com.javalec.ex; public class ThreadTest implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()); //static으로 선언 되어있는데 Thread.currentThread() //현재 구동이 되고있는데 name을 반환, Thread에 이름을 구하는것 System.out.println("ThreadTest"); for (int i = 0; i < 10; i++) { System.out.println("i=" + i); try { Thread.sleep(500); //0.5초동안 잠시 쉬는것 } catch (Exception e) { } } } } | cs |
Thread 클래스를 상속 통한 Thread
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package com.javalec.ex; public class MainClass { public static void main(String[] args) { ThreadTest threadTest = new ThreadTest(); threadTest.setName("A"); threadTest.start(); System.out.println(Thread.currentThread().getName()); System.out.println("MainClass"); //main thread에 이름을 출력함 //스레드는 따로 행동하기 때문에 위에 start로 Ruunable을 실행하더라도 신경쓰지않고 따로 실행을함 } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package com.javalec.ex; public class ThreadTest extends Thread{ @Override public void run() { System.out.println(Thread.currentThread().getName()); //static으로 선언 되어있는데 Thread.currentThread() //현재 구동이 되고있는데 name을 반환, Thread에 이름을 구하는것 System.out.println("ThreadTest"); for (int i = 0; i < 10; i++) { System.out.println("i=" + i); try { Thread.sleep(500); //0.5초동안 잠시 쉬는것 } catch (Exception e) { } } } } | cs |
객체 1개, 스레드 n개
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package com.javalec.ex; public class ThreadTest implements Runnable { int testNum = 0; @Override public void run() { for (int i = 0; i < 10; i++) { if(Thread.currentThread().getName().equals("A")) { System.out.println("===================================="); testNum++; } System.out.println("Thread Name : " + Thread.currentThread().getName() + ", testNum : " + testNum); try { Thread.sleep(500); } catch (Exception e) {} } } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.javalec.ex; public class MainClass { public static void main(String[] args) { ThreadTest threadTest = new ThreadTest(); Thread thread0 = new Thread(threadTest, "A"); Thread thread1 = new Thread(threadTest, "B"); thread0.start(); thread1.start(); System.out.println(Thread.currentThread().getName()); System.out.println("MainClass"); } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package com.javalec.ex; public class ThreadTest implements Runnable { int testNum = 0; @Override public void run() { for (int i = 0; i < 10; i++) { if(Thread.currentThread().getName().equals("A")) { System.out.println("===================================="); testNum++; } System.out.println("Thread Name : " + Thread.currentThread().getName() + ", testNum : " + testNum); try { Thread.sleep(500); } catch (Exception e) {} } } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package com.javalec.ex; public class MainClass { public static void main(String[] args) { ThreadTest threadTest0 = new ThreadTest(); ThreadTest threadTest1 = new ThreadTest(); Thread thread0 = new Thread(threadTest0, "A"); Thread thread1 = new Thread(threadTest1, "B"); thread0.start(); thread1.start(); System.out.println(Thread.currentThread().getName()); System.out.println("MainClass"); } } | cs |
synchronized
Synchronized의 사전적 의미는 통합, 동시 정도의 의미 입니다.
위에서 살펴본 봐와 같이 JAVA 멀티스레에서 하나의 객체에 n개의 스레드가 진행될 경우가 있습니다. 이런 경우 문제가 생길 수 있습니다.
객체에 선언되어 있는 인스턴스변수를 스레드에서 공유 하게 되어, 인스턴스의 값에 영향을 미치게 됩니다.
이런 경우를 대비해서 JAVA에서는 synchronized라는 키워드를 이용합니다. Synchronized는 먼저 수행되는 스레드의 모든 작업이 끝날 때까지 다른 스레드는 기다려야 하는 방식 입니다.
쉽게 식당 예를 들어 보겠습니다. 점심 시간에 식당에 가면 사람이 많아 비어있는 테이블이 없을 수 있습니다. 그런 경우 우리는 식당 문 앞에서 기다리다가 먼저 온 순서대로 빈자리에 앉습니다. 만약 다른 사람이 식사하고 있는 테이블에 같이 앉아서 식사를 한다면, 반찬도 공유되고, 밥도 공유되어 엉망이 되어 버릴 것입니다. 스레드도 마찬가지라고 생각 하시면 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package com.javalec.ex; public class ThreadTest implements Runnable { int testNum = 0; @Override public synchronized void run() { //synchronized 추가 for (int i = 0; i < 10; i++) { if(Thread.currentThread().getName().equals("A")) { System.out.println("===================================="); testNum++; } System.out.println("Thread Name : " + Thread.currentThread().getName() + ", testNum : " + testNum); try { Thread.sleep(500); } catch (Exception e) {} } } } | cs |
//synchronized 를 추가하면 A 스레드가 전부 실행되고 그 다음에 B 스레드가 실행이 된다.
**출력화면
====================================
MainClass
Thread Name : A, testNum : 1
====================================
Thread Name : A, testNum : 2
====================================
Thread Name : A, testNum : 3
====================================
Thread Name : A, testNum : 4
====================================
Thread Name : A, testNum : 5
====================================
Thread Name : A, testNum : 6
====================================
Thread Name : A, testNum : 7
====================================
Thread Name : A, testNum : 8
====================================
Thread Name : A, testNum : 9
====================================
Thread Name : A, testNum : 10
Thread Name : B, testNum : 10
Thread Name : B, testNum : 10
Thread Name : B, testNum : 10
Thread Name : B, testNum : 10
Thread Name : B, testNum : 10
Thread Name : B, testNum : 10
Thread Name : B, testNum : 10
Thread Name : B, testNum : 10
Thread Name : B, testNum : 10
Thread Name : B, testNum : 10
'Programming > JAVA' 카테고리의 다른 글
JAVA (java.lang 패키지 /오토박싱) (0) | 2018.05.14 |
---|---|
배열(Array), ArrayList 차이점 및 활용 (0) | 2018.05.09 |
JAVA 입출력(I/O) (0) | 2018.05.03 |
Map 계열 컬렉션 (0) | 2018.05.02 |
List 계열 컬렉션 <ArrayList> (0) | 2018.05.02 |