IT 개발노트
스레드 본문
1. JAVA 스레드
1.1 멀티 프로세스
: 멀티 프로세스란 컴퓨터가 여러 가지 일을 동시에 작업하는 것이다.
1.2 스레드(멀티 스레드)
: 하나의 프로세스에서 다시 여러 가지 일을 하는 것을 뜻한다.
예)
: 동일한 채팅프로그램에서 파일전송과 채팅을 동시에 하고 있는 것.
1.2.1 스레드의 형태
- JAVA는 기본적으로 멀티스레드를 지원하고 있다.
- 객체 하나를 n개의 스레드가 공유하는 방식
- 객체 하나당 하나의 스레드가 존재하는 방식
1.3 멀티스레드 문법
- Runnable인터페이스 구현을 통한 Thread
- Thread클래스 상속을 통한 Thread
1.3.1 Runnable인터페이스 구현을 통한 Thread
- 스레드 1개, 객체 1개인 경우
예시
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package sungju.Java.JavaProject; public class MainClass { public static void main(String[] args) { ThreadTest threadTest = new ThreadTest(); Thread thread = new Thread(threadTest, "A"); // start메서드를 호출해 주어야 run메서드를 호출해주어 실행이 된다. thread.start(); // 현재 구동이 되고 있는 스레드의 이름을 구하기 System.out.println(Thread.currentThread().getName()); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package sungju.Java.JavaProject; public class ThreadTest implements Runnable { @Override public void run() { // 현재 구동이 되고 있는 스레드의 이름을 구하기 System.out.println(Thread.currentThread().getName()); System.out.println("ThreadTest"); for(int i=0; i<10; i++) { System.out.println("i = " + i); try { // ThreadTest가 한번 실행되면 0.5초 딜레이 Thread.sleep(500); } catch (Exception e){} } } } |
1.3.2 Thread클래스 상속을 통한 Thread
- 스레드 1개, 객체 1개인 경우
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package sungju.Java.JavaProject; public class MainClass { public static void main(String[] args) { ThreadTest threadTest = new ThreadTest(); threadTest.setName("B"); // start메서드를 호출해 주어야 run메서드를 호출해주어 실행이 된다. threadTest.start(); // 현재 구동이 되고 있는 스레드의 이름을 구하기 System.out.println(Thread.currentThread().getName()); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package sungju.Java.JavaProject; public class ThreadTest extends Thread { @Override public void run() { // 현재 구동이 되고 있는 스레드의 이름을 구하기 System.out.println(Thread.currentThread().getName()); for(int i=0; i<10; i++) { System.out.println("i = " + i); try { // ThreadTest가 한번 실행되면 0.5초 딜레이 Thread.sleep(500); } catch (Exception e){} } } } |
1.3.3 스레드 n개, 객체 1개일때와 스레드 1개, 객체 1개일때의 차이점
- 스레드 n개, 객체 1개인 경우
예시
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package sungju.Java.JavaProject; 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"); // start메서드를 호출해 주어야 run메서드를 호출해주어 실행이 된다. thread0.start(); thread1.start(); // 현재 구동이 되고 있는 스레드의 이름을 구하기 System.out.println(Thread.currentThread().getName()); } } |
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 sungju.Java.JavaProject; public class ThreadTest implements Runnable { int testNum = 0; @Override public void run() { for(int i=0; i<10; i++) { // A쓰레드가 실행되면 testNum을 1씩 증가시키겠다. if(Thread.currentThread().getName().equals("A")) { System.out.println("============================"); testNum++; } System.out.println("Thread Name : " + Thread.currentThread().getName() + ", testNum : " + testNum); try { // ThreadTest가 한번 실행되면 0.5초 딜레이 Thread.sleep(500); } catch (Exception e){} } } } |
- 스레드 1개, 객체 1개인 경우
예시
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package sungju.Java.JavaProject; 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"); // start메서드를 호출해 주어야 run메서드를 호출해주어 실행이 된다. thread0.start(); thread1.start(); // 현재 구동이 되고 있는 스레드의 이름을 구하기 System.out.println(Thread.currentThread().getName()); } } |
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 sungju.Java.JavaProject; public class ThreadTest implements Runnable { int testNum = 0; @Override public void run() { for(int i=0; i<10; i++) { // A쓰레드가 실행되면 testNum을 1씩 증가시키겠다. if(Thread.currentThread().getName().equals("A")) { System.out.println("============================"); testNum++; } System.out.println("Thread Name : " + Thread.currentThread().getName() + ", testNum : " + testNum); try { // ThreadTest가 한번 실행되면 0.5초 딜레이 Thread.sleep(500); } catch (Exception e){} } } } |
- 객체가 1개일때 스레드가 n개이면 A스레드에서 상태변화가 생기면 B스레드에도 영향이 미친다.
- 객체가 1개일때 스레드가 1개이면 A스레드와 B스레드는 별개로 취급되어 A스레드에 상태변화가 생겨도 B스레드에 영향을 미치지 않는다.
예제
: 선거 개표방송에서 지역1, 지역2, 지역3의 개표율이 엎치락 뒤치락 하는 것을 Thread를 이용하여 만들어보기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package sungju.Java.JavaProject; public class MainClass { public static void main(String[] args) { VoteThread voteLocation1 = new VoteThread(); VoteThread voteLocation2 = new VoteThread(); VoteThread voteLocation3 = new VoteThread(); Thread location1 = new Thread(voteLocation1, "Location1"); Thread location2 = new Thread(voteLocation2, "Location2"); Thread location3 = new Thread(voteLocation3, "Location3"); // start메서드를 호출해 주어야 run메서드를 호출해주어 실행이 된다. location1.start(); location2.start(); location3.start(); } } |
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | package sungju.Java.JavaProject; import java.util.Random; public class VoteThread implements Runnable{ // 개표율 int targetNum = 100; int sum = 0; Random random = new Random(); @Override public void run() { StringBuffer sb = new StringBuffer(); while(true) { sum = sum + random.nextInt(10); // sb를 초기화 (0~끝까지) sb.delete(0, sb.toString().length()); // sum이 targetNum 보다 클때 즉 개표율이 100을 넘길때 if(sum>=targetNum) { // sum을 100으로 변경 sum = 100; // *을 100개 찍는다. for(int i=0; i<sum; i++) { sb.append("*"); } System.out.println(Thread.currentThread().getName() + " 개표율 : " + sum + "\t: " + sb); break; } else { for(int i=0; i<sum; i++) { sb.append("*"); } System.out.println(Thread.currentThread().getName() + " 개표율 : " + sum + "\t: " + sb); } try { Thread.sleep(200); } catch(Exception e) {} } } } |
1.4 synchronized
: JAVA 멀티 스레드에서 하나의 객체에 n개의 스레드가 진행될 경우가 있는데, 이런 경우 문제가 생길 수 있다.
객체에 선언되어 있는 인스턴스변수를 스레드에서 공유하게 되어, 인스턴스의 값에 영향을 미치게 된다.
이런 경우를 대비해서 JAVA에서는 synchronized라는 키워드를 이용한다.
Synchronized는 먼저 수행되는 스레드의 모든 작업이 끝날 때까지 다른 스레드는 기다려야 하는 방식이다.
예시
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package sungju.Java.JavaProject; 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"); } } |
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 sungju.Java.JavaProject; public class ThreadTest implements Runnable { int testNum = 0; @Override public synchronized void run() { for(int i=0; i<10; i++) { // A쓰레드가 실행되면 testNum을 1씩 증가시키겠다. if(Thread.currentThread().getName().equals("A")) { System.out.println("============================"); testNum++; } System.out.println("Thread Name : " + Thread.currentThread().getName() + ", testNum : " + testNum); try { // ThreadTest가 한번 실행되면 0.5초 딜레이 Thread.sleep(500); } catch (Exception e){} } } } |
'기초튼튼 > JAVA' 카테고리의 다른 글
숫자맞추기 게임 (0) | 2019.02.18 |
---|---|
제네릭스(Generics) (0) | 2019.02.12 |
JAVA 입출력(I/O) 알아보기 (0) | 2019.02.10 |
컬렉션이란 (0) | 2019.02.07 |
예외처리 (0) | 2019.01.30 |