main쓰레드
main 메서드 의 코드를 수행하는 쓰레드
예를들어 우리가 main메서드를 실행하면
위가 바로 메인쓰레듣가
쓰레드는 사용자쓰레드와 데몬쓰레드, 두 종류가 있다.
데몬쓰레드 : 간단히 얘기해서 사용자 쓰레드의 보조 역할,
실행 중인 사용자 쓰레드가 하나도 없을 때 프로그램은 종료된다.
메인쓰레드가 종료되면 전체 프로그램이 종료되었지만, 멀티쓰레드 프로그램에서 아직 실행중인 쓰레드가 있다면 프로그램은 종료되지 않는다.
싱글쓰레드와 멀티쓰레드 프로스세의 차이를 보다 깊이 알아보자
하나의 쓰레드로 두개의 작업을 수행을 시켜보자,
AAAAABBBBB
한개의 쓰레드가 끝나고 두번째 쓰레드가 시작된다.
그런데 또다른 프로그램은 두개의 쓰레드로 두개의 작업 수행시키면
ABABABABAB
번갈아 가며 시작한다. 이때, 싱글쓰레드로 작업한 시간보다 더 걸리게 되기까지 한다.
이유는 쓰레드간의 작업 전환에 시간이 걸리기 때문이다.
쉽게 설명해서
작업 전활 할 때 현재 진행중인 작업의 상태등의 정보를 저장하고 읽어오는 시간이있어 알트탭 계속하면 오래걸리듯이...
그래서 그작업들을 계속불러와야해서 느린컴에선 두가지작업을 지양하는 것이기도 하다.
즉 단순작업, CPU만을 사용하는 계산작업이라면 오히려 멀티쓰레드보다 싱글쓰레드로 프로그래밍하는것이 효율적이다.
예제르 통해 알아보자
package ch13.Thread;
public class ThreadEx4 {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < 300; i++) {
System.out.printf("%s", new String("-"));
}
System.out.println("소요시간 : " + (System.currentTimeMillis() - startTime));
for (int i = 0; i < 300; i++) {
System.out.printf("%s", new String("|"));
}
System.out.println("소요시간2 : " + (System.currentTimeMillis() - startTime));
}
}
싱글쓰레드 방식으로 코드를 짜고 실행해보았다. 쓰레드시작전의 시간을 변수로 정한뒤 각 쓰레드의 시작과 종료시간을 쟀다.
깔끔하게 순서대로 진행했다. 그리고 소요시간 37, 48 값을 알 수 있다.
멀티쓰레드로 진행했을때
package ch13.Thread;
public class ThreadEx5 {
static long startTime = 0;
public static void main(String[] args) {
ThreadEx5_1 th1 = new ThreadEx5_1();
th1.start();
startTime = System.currentTimeMillis();
for (int i = 0; i < 300; i++) {
System.out.printf("%s", new String("-"));
}
System.out.println("소요시간(메인메서드) : " + (System.currentTimeMillis() - startTime));
}
}
class ThreadEx5_1 extends Thread {
public void run() {
for (int i = 0; i < 300; i++) {
System.out.printf("%s", new String("|"));
}
System.out.println("소요시간(쪼인) : " + (System.currentTimeMillis() - ThreadEx5.startTime));
}
}
우선 Ex5_1이라는 클래스의 쓰레드와 메인메서드를 순차적으로 돌리는 예제이다.
사진과 같이 섞여서 나온다. 그리고 값도 71, 67로, 싱글메서드보다 훨씬 높은 숫가값을 얻게되었다.
이걸 문맥전환이라고 한다.(Context Switching)
이때 시간이 소요가 된다. 동시에 작업이 번갈아 가면서 진행은 되지만 오히려 시간이 더걸림을 알 수 있다.
※이것도 어떤 쓰레드가 먼저 실행될지는 모른다 왜? OS스케줄러때문에...
-그럼 멀티쓰레드로 돌리는 이유가 뭔가? 시간이 더 걸린다며!! : 시간이 더 걸려도 2가지 작업을 동시에 할 수있음이 엄청 큰 장점이다
-또다른 장점은 작업을 더 효율적으로 할 수 있으니까!
쓰레드의 I/O 블락킹(blocking)
I/O ? input, output(입출력)을 줄인것이다. , Blocking = 막힘, 제한, 통제 등
입출력에 대해 어떤 영향을 받는지 , 그리고 영향을 끼치는지 공부해 보겠다.
package ch13.Thread;
import javax.swing.JOptionPane;
public class ThreadEx6 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String input = JOptionPane.showInputDialog("아무값이나 입력하세요.");
System.out.println("your entered is " + input);
for (int i = 10; i > 0; i--) {
System.out.println(i);
try {
Thread.sleep(1000);
} catch (Exception e) {
}
}
}
}
위의 예제는 메인메서드에서 입력받는 창을 띄운다 -> 사용자가 입력한다 -> 출력한다.(sop문)-> 카운트 다운 시작
그런데! 이것은 순차적으로 실행이된다. 만약, 사용자가 입력을 하지않고 가만히 있으면, 카운트 다운은 그에 맞게 시작이 되지 않는다. 즉 멈춤현상이있다. 그 시간동안 프로그램은 '정지' 상태이다.
package ch13.Thread;
import javax.swing.JOptionPane;
public class ThreadEx7 {
public static void main(String[] args) {
// TODO Auto-generated method stub
ThreadEx7_1 th = new ThreadEx7_1();
th.start();
String input = JOptionPane.showInputDialog("아무값이나 입력하세요.");
System.out.println("당신이 입력한 값 : " + input);
}
}
class ThreadEx7_1 extends Thread {
public void run() {
for (int i = 10; i > 0; i--) {
System.out.println(i);
try {
sleep(1000);
} catch (Exception e) {
}
}
}
}
멀티쓰레드 프로그램을 작성했다. 메인메서드에서 작동되면서 카운트다운이 시작되고, 그와 별개로 입력을 받고 출력하는 작업이 또다르게 진행된다.
왜냐? A쓰레드가 작동해도 B쓰레드에 새로 스택이 생겨서, B에 입력을 하지않더라도 A는 계속 카운트다운이 시작되고 끝날때까지 별개로 진행된다!
싱글쓰레드에서 입출력쓰레드에서 사용자가 아무것도안하면 그 다음 쓰레드는 아무것도 안한다. 멀티의 경우 사용자 입력하는 부분에서 무엇을 하더라도 별개로 진행된다.
외부장치거나 다른기기와 연결, 그리고 파일을 쓰거나, 입출력등 CPU작업이 아닌 다른 작업일 때는 멀티쓰레드가 더 효율적이다.
---한가지 개인적으로 궁금해서 테스트를 하나더해봤다.
Q : 그럼 카운트다운 쓰레드 1이 진행중일때 입출력 쓰레드를 띄우고, 또 그 이후 새로운 쓰레드가 실행된다면 어떻게 나올까?
package ch13.Thread;
import javax.swing.JOptionPane;
public class ThreadEx7 {
public static void main(String[] args) {
// TODO Auto-generated method stub
ThreadEx7_1 th1 = new ThreadEx7_1();
ThreadEx7_2 th2 = new ThreadEx7_2();
th1.start();
String input = JOptionPane.showInputDialog("아무값이나 입력하세요.");
System.out.println("당신이 입력한 값 : " + input);
th2.start();
}
}
class ThreadEx7_1 extends Thread {
public void run() {
for (int i = 10; i > 0; i--) {
System.out.println("-----쓰레드 1의 카운트 다운 : " + i + "-----");
try {
sleep(1000);
} catch (Exception e) {
}
if (i == 1) {
System.out.println("쓰레드 1종료");
}
}
}
}
class ThreadEx7_2 extends Thread {
public void run() {
for (int i = 10; i > 0; i--) {
System.out.println("=====쓰레드 2의 카운트 다운 : " + i + "=====");
try {
sleep(1000);
} catch (Exception e) {
}
if (i == 1) {
System.out.println("쓰레드 2종료");
}
}
}
}
그래서 쓰레드를 하나더만들고 종료하게 된다면 ?!
오케이 입력과 동시에 시작하는군
그럼 진짜 마지막으로 쓰레드 1이 끝나면 쓰레드 2가 다끝나지도 않은상태서 강제로 종료되게끔,
System.exit(0); 를 추가한다면 강제종료가될까? 혹은 쓰레드 2가 끝날때 까지 계속될까?
class ThreadEx7_1 extends Thread {
public void run() {
for (int i = 10; i > 0; i--) {
System.out.println("-----쓰레드 1의 카운트 다운 : " + i + "-----");
try {
sleep(1000);
} catch (Exception e) {
}
if (i == 1) {
System.out.println("쓰레드 1종료");
System.exit(0);
}
}
}
}
if절 마지막에 exit()문을 넣고 실행했다.
당연한 결과지만 종료와함꼐 강제종료되었다.
'JAVA공부 > 2-쓰레드' 카테고리의 다른 글
쓰레드 제어문(1) (0) | 2021.10.13 |
---|---|
데몬 쓰레드와 쓰레드의 상태(실행제어) (0) | 2021.10.12 |
쓰레드의 우선순위, 그룹 (0) | 2021.10.12 |
쓰레드의 구현과 실행 (0) | 2021.10.07 |
프로세스와 쓰레드 (0) | 2021.10.07 |
댓글