일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 요리
- ubuntu
- linux
- db
- Web Server
- JVM
- Design Patterns
- tool
- elasticsearch
- jenkins
- java
- Gradle
- php
- springboot
- laravel
- IntelliJ
- Spring Batch
- Oracle
- 맛집
- Spring Boot
- javascript
- Git
- MySQL
- jsp
- devops
- AWS
- ReactJS
- redis
- it
- Spring
- Today
- Total
아무거나
스레드(Thread) 본문
[JAVA 스레드]
멀티 프로세스 : 컴퓨터가 여러 가지 일을 동시에 하고 있는 것을 뜻함.
스레드(멀티스레드) : 위에서 말한 하나의 프로세스에서 다시 여러 가지 일을 하는 것을 뜻 합니다. 예를 들어 파일을 전송하면서
채팅을 하고 있다. 동일한 채팅프로그램에서 파일전송과 채팅을 동시에 하고 있는 것 입니다.
채팅 프로그램 프로세스 -> 파일전송 스레드
-> 채팅 스레드
JAVA는 기본적으로 멀티스레드를 지원 하고 있습니다.
스레드는 두 가지 형태로 존재 합니다.
방식1) 객체 하나를 n개의 스레가 공유 하는 방식
스레드0 ->
스레드1 -> 객체0
스레드2 ->
방식2) 객체 하나당 하나의 스레드가 존재하는 방식이다.
스레드0 -> 객체0
스레드1 -> 객체1
스레드2 -> 객체2
# 멀티 스레드 문법
* run method를 반드시 구현 하여야 한다.
(어떤 일을할때의 로직이 run 메소드안에서 구현되어야 한다. 즉 Thread가 하는 일들이 모여있다.)
1. Runnable 인터페이스 구현을 통한 Thread
* Main Thread에서 내가 만든 Thread를 사용할 떄의 예시이다.
ex) [MainClass.java]
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());
System.out.println("MainClass");
}
}
[ThreadTest.java]
public class ThreadTest implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()); // Thread 이름
System.out.println("ThreadTest");
for (int i=0; i<10; i++) {
System.out.println("i =" + i);
try {
// Thread를 사용할땐 try ~ catch 안에 구현가능
Thread.sleep(1000); // 컴퓨터 안에서 돌아가는 시간대가 다르므로 정확한 시간이 아니다(컴퓨터 성능별로 차이가 있음)
} catch (Exception e) {
}
}
}
}
[결과]
// main이 먼저 찍히는 이유는 run()에서 Thread가 도는것과 main이 하는것과는 별개다
// 그러므로 main은 thread가 돌던말던 자기 할일을 끝내기 때문에 main이 먼저 출력된 것이다.
main
MainClass
A
ThreadTest
i =0
i =1
i =2
i =3
i =4
i =5
i =6
i =7
i =8
i =9
2. Thread 클래스를 상속 통한 Thread
ex) [MainClass.java]
public class MainClass {
public static void main(String[] args) {
ThreadTest threadTest = new ThreadTest();
threadTest.setName("B");
threadTest.start();
System.out.println(Thread.currentThread().getName());
}
}
[ThreadTest.java]
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);
try {
Thread.sleep(500);
} catch (Exception e) {}
}
}
}
[결과]
main
B
0
1
2
3
4
5
6
7
8
9
3. 객체 1개, 스레드n개가 돌아가는 방식
[MainClass.java]
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());
}
}
[ThreadTest.java]
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) {}
}
}
}
[결과]
main
Thread Name : B, testNum: 0
======================
Thread Name : A, testNum: 1
======================
Thread Name : B, testNum: 1 // A일때만 ++해야되는데 B일경우에 오른 이유는 MainClass에서 thread0과 thread1가 같은 threadTest객체를 공유해서이다.
Thread Name : A, testNum: 2
======================
Thread Name : B, testNum: 2
Thread Name : A, testNum: 3
======================
Thread Name : A, testNum: 4
Thread Name : B, testNum: 3
======================
Thread Name : A, testNum: 5
Thread Name : B, testNum: 4
Thread Name : B, testNum: 5
======================
Thread Name : A, testNum: 6
======================
Thread Name : A, testNum: 7
Thread Name : B, testNum: 6
======================
Thread Name : A, testNum: 8
Thread Name : B, testNum: 7
======================
Thread Name : A, testNum: 9
Thread Name : B, testNum: 8
======================
Thread Name : A, testNum: 10
Thread Name : B, testNum: 9
4. 객체1개, 스레드1개
-> 위의 3번이랑 좀 다르게 객체를 구분해서 하면 A일때만 ++가된다.
ex) [MainClass.java]
ThreadTest threadTest0 = new ThreadTest();
ThreadTest threadTest1 = new ThreadTest();
Thread thread0 = new Thread(threadTest0, "A");
Thread thread1 = new Thread(threadTest1, "B");
5. 선거 개표 방송 예제
-> 선거 개표방송에서 지역1, 지역2, 지역3의 개표율이 엎치락 뒤치락 하는 것을 Thread를 이용하여 만들자.
ex) [MainClass.java]
public class MainClass {
public static void main(String[] agrs) {
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");
location1.start();
location2.start();
location3.start();
}
}
[VoteThread.java]
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.delete(0, sb.toString().length()); // 그래프 초기화(**로 만들어지는 그래프)
if(sum >= targetNum) {
sum = 100;
for (int i=0; i
sb.append("*");
}
System.out.println(Thread.currentThread().getName() + " 개표율 : " + sum + "\t: " +sb);
break;
} else {
for (int i=0; i
sb.append("*");
}
System.out.println(Thread.currentThread().getName() + " 개표율 : " + sum + "\t: " + sb);
}
try {
Thread.sleep(200);
} catch (Exception e) {}
}
}
}
* 이렇게 하면 객체를 공유하지않고 Thread별로 실행이 가능하다.
6. Synchronized
-> Synchronized의 사전적 의미는 통합, 동시 정도의 의미이다.
위에서 살펴본 바와 같이 JAVA 멀티스레드에서 하나의 객체에 n개의 스레드가 진행될 경우가 있다. 이런 경우 문제가 발생할 수 있다.
객체에 선언되어 있는 인스턴스 변수를 스레드에서 공유 하게 되어, 인스턴스의 값에 영향을 미치게 된다.
이런 경우를 대비해서 JAVA에서는 Synchronized라는 키워드를 사용한다.
* Synchronized는 먼저 수행되는 스레드의 모든 작업이 끝날 때까지 다른 스레드는 기다려야하는 방식 입니다.
ex) 식당에 가면 사람이 많아 비어있는 테이블이 없을 수 있다. 그런 경우 우리는 식당 문 앞에서 기다리다가 먼저 온 순서대로
빈자리에 앉습니다. 만약 다른 사람이 식사하고 있는 테이블에 같이 앉아서 식사를 한다면, 반찬도 공유되고, 밥도 공유되어
엉망이 될 것이다. 스레드도 마찬가지라고 생각 하면 된다.
스레드0 ->
스레드1 -> 객체0
스레드2 ->
[MainClass.java]
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());
}
}
[ThreadTest.java]
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) {}
}
}
}
[결과]
main
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
======================
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
'Java & Kotlin > Java' 카테고리의 다른 글
JAVA 네트워크 (0) | 2019.08.17 |
---|---|
JAVA 그래픽 (0) | 2019.08.16 |
입출력(I/O) (0) | 2019.08.16 |
JAVA Collections (0) | 2019.08.16 |
예외처리 (0) | 2019.08.16 |