※ 스레드
1. 프로세스와 스레드
- 프로세스 : 실행중인 프로그램을 의미함
- 스레드 프로세스안에서 작업을 수행하는게 스레드
- 두개이상의 스레드를 가진 프로세스를 멀티스레드 프로세스라고 부름
-
1-1) 멀티스레드
* 멀티스레드의 장점
- cpu, 메모리를 효율적으로 사용할 수 있음
- 사용자에대한 응답성이 높아짐 (멀티스레드를 쓰는 가장 큰 이유)
- 작업을 스레드 단위로 분리해서 실행시간을 줄일 수 있다. (케바케)
- 블럭, 락, 스레드큐의 대기열, 작업전환,
- 작업우선순위 (JRT)
- 여러 스레드들이 메모리나 컴퓨터 자원을 공유해서 사용하기 때문에 동기화가 제대로 되지 않거나
-
예제) 자바에서 다른 프로그램을 실행하는 예제
package chapter17;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
public class ProcessEx {
public static void main(String[] args) throws IOException, InterruptedException{
Process p1 = Runtime.getRuntime().exec("notepad");
Process p2 = Runtime.getRuntime().exec("mspaint");
Process p3 = Runtime.getRuntime().exec("help");
p1.waitFor();
p2.destroy();
InputStream is = p3.getInputStream();
Reader reader = new InputStreamReader(is, "ms949");
int b = 0;
while((b = reader.read()) != -1) {
System.out.print((char)b);
}
}
}
실행시 메모장, 그림판이 실행되며 help는 p1작업 즉 그림판의 작업이 다 끝날때까지(p1.waitFor) 기다렸다 프로그램이 종료되면
콘솔창에 help가 출력된다.
help는 cmd창의 아래 사진과 같다,
1-2) 스레드 생성과 실행
- 스레드를 생성하는 방법은 크게 두가지다.
- Thread 클래스를 상속받는 방법
- Runnable 인터페이스를 구현한 객체를 Thread 객체에 넣어주는 방식 (자주사용)
*스레드에 대한 해석
멀티스레드는 JVM에서 호출스택에 스레드 수 만큼 실행된다.
아래 예제에서 호출스택 첫번째 컵에 main에 start가 실행되고
두번째ㅔ 컵에 run이 실행되며 스레드의 이름은 - 이다.
run이 실행되면 main에 있는 start가 사라지고
두번째 t2가 실행되면 main에 있는 start가 사라지고 두번째 컵이 생겨 작업을 처리한다.
멀티스레드 환경에선 어느 작업을 먼저 할것인지 모른다.
이것에 대한 작업지시는 운영체제가 한다.
아래 예제에 2000이 출력되면 main은 끝나서 프로그램이 종료된거 같지만
호출스택에 있는 run이 실행중이라 아직 끝난것이 아니다.
main이 먼저 끝나도 run이 할일을 다하면 프로그램이 종료된다.
*프로그램 종료 코드 : System.exit(0);
예제1) Thread 클래스 상속
package chapter17;
public class ThreadEx extends Thread {
// 이 프로그램은 총 3개의 스레드가 동작한다 (메인1 메인밑2)
public void run() {
for(int i=0; i < 1000; i++) {
System.out.print(getName()); // getName은 스레드 클레스가 가지고있는 메서드
}
}
public static void main(String[] args) {
Thread t1 = new ThreadEx();
// 스레드 이름 "-"
t1.setName("-");
Thread t2 = new ThreadEx();
// 스레드 이름 "|"
t2.setName("|");
t1.start();
t2.start();
// 순서대로 처리 스레드와는 다름
// t1.run();
// t2.run();
String str = "-----||||||||||-----------------------------|||||||||||||||||||||||||||-------------------------------------------------------|-----------------|||||||||||||---------------------------------------------------------------------------------------------------------------------------------------||||||||||||----------------|||||||||||||----------------------|||||||||||||||||||||||---||||||||||||||||||||||||||||||||||--------------------||||||||||||||||----------||||||||||||||||||||||||||||||||||||||||||||------------------------------|||||||||||||||||---------------------------------------------------||-----|||||||||||||||||||||||||------||------||||||||||||||||||---------------------|||||-------------------||----------||------------------------------|||||--------||||||-----------|||||||||||||||||||-----|||||||----||||-----||||--------------|||---|||-----------------------|||||||||||||||||||||||--------|||||||||||--||||----------------||||||||||||||||--|||---|||||||||----|||||||||||------||||||||||||||------||||-||||----||||||----|||||||||||------|||-----|||||||||||||||||-----------|||||||||------|||||||||||||||||||||------------|||||||||||||||||||--|||||||||||||||--|||||||||||||||||||||||||||||||||||||||||||||||||-|||||-||||||||||||||||||||||--|---------||------------------------||----||||||---|||||----||||||||||||||----|||||||||||||||||||------||||||--||||||||||||--||||||||||||||||||---||||||-------------|||----|||||--||||-------||||----||----||----||----||------||||||||||----||------|||||||----------------|-----|||||--||||---||------|||||||||--||||------||-----||||------||||||||-----------------||--|||||||||||||||||||||||||||----------------------|||||||------||||||||||----||||----|||||||||||||||||||||||------||||---------------||||||||----------------------||||||--||||----------------------||---||||----|||||||||||||----||||||----||||||||||--------||||||||||||||||||||||||||||||||||||||||||||||||||||||||||-------||||||||-----------||||||||||||||||||||||||||||||||||||||";
System.out.println(str.length());
// 프로그램에 종료
System.exit(0);;
}
}
예제2)
package chapter17;
import java.io.IOException;
import java.nio.CharBuffer;
// Thread클래스 상속
public class ThreadEx extends Thread {
// 이 프로그램은 총 3개의 스레드가 동작한다 (메인1 메인밑2)
public void run() {
for(int i=0; i < 1000; i++) {
System.out.print(getName()); // getName은 스레드 클레스가 가지고있는 메서드
}
}
public static void main(String[] args) {
Thread t1 = new ThreadEx();
// 스레드 이름 "-"
t1.setName("-");
Thread t2 = new ThreadEx();
// 스레드 이름 "|"
t2.setName("|");
t1.start();
t2.start();
Thread t3 = new Thread(new MyClass());
t3.start();
// 순서대로 처리 스레드와는 다름
// t1.run();
// t2.run();
String str = "-----||||||||||-----------------------------|||||||||||||||||||||||||||-------------------------------------------------------|-----------------|||||||||||||---------------------------------------------------------------------------------------------------------------------------------------||||||||||||----------------|||||||||||||----------------------|||||||||||||||||||||||---||||||||||||||||||||||||||||||||||--------------------||||||||||||||||----------||||||||||||||||||||||||||||||||||||||||||||------------------------------|||||||||||||||||---------------------------------------------------||-----|||||||||||||||||||||||||------||------||||||||||||||||||---------------------|||||-------------------||----------||------------------------------|||||--------||||||-----------|||||||||||||||||||-----|||||||----||||-----||||--------------|||---|||-----------------------|||||||||||||||||||||||--------|||||||||||--||||----------------||||||||||||||||--|||---|||||||||----|||||||||||------||||||||||||||------||||-||||----||||||----|||||||||||------|||-----|||||||||||||||||-----------|||||||||------|||||||||||||||||||||------------|||||||||||||||||||--|||||||||||||||--|||||||||||||||||||||||||||||||||||||||||||||||||-|||||-||||||||||||||||||||||--|---------||------------------------||----||||||---|||||----||||||||||||||----|||||||||||||||||||------||||||--||||||||||||--||||||||||||||||||---||||||-------------|||----|||||--||||-------||||----||----||----||----||------||||||||||----||------|||||||----------------|-----|||||--||||---||------|||||||||--||||------||-----||||------||||||||-----------------||--|||||||||||||||||||||||||||----------------------|||||||------||||||||||----||||----|||||||||||||||||||||||------||||---------------||||||||----------------------||||||--||||----------------------||---||||----|||||||||||||----||||||----||||||||||--------||||||||||||||||||||||||||||||||||||||||||||||||||||||||||-------||||||||-----------||||||||||||||||||||||||||||||||||||||";
System.out.println(str.length());
// 프로그램에 종료
// System.exit(0);
}
}
// Runnable 인터페이스 구현
class MyClass implements Runnable {
public void run() {
for(int i=0; i<1000; i++) {
System.out.print("*");
}
}
}
예제3) 종합
package chapter17;
import java.io.IOException;
import java.nio.CharBuffer;
// Thread클래스 상속
public class ThreadEx extends Thread {
// 이 프로그램은 총 3개의 스레드가 동작한다 (메인1 메인밑2)
public void run() {
for(int i=0; i < 1000; i++) {
System.out.print(getName()); // getName은 스레드 클레스가 가지고있는 메서드
}
}
public static void main(String[] args) {
Thread t1 = new ThreadEx();
// 스레드 이름 "-"
t1.setName("-");
Thread t2 = new ThreadEx();
// 스레드 이름 "|"
t2.setName("|");
t1.start();
t2.start();
Thread t3 = new Thread(new MyClass());
t3.start();
// 순서대로 처리 스레드와는 다름
// t1.run();
// t2.run();
String str = "-----||||||||||-----------------------------|||||||||||||||||||||||||||-------------------------------------------------------|-----------------|||||||||||||---------------------------------------------------------------------------------------------------------------------------------------||||||||||||----------------|||||||||||||----------------------|||||||||||||||||||||||---||||||||||||||||||||||||||||||||||--------------------||||||||||||||||----------||||||||||||||||||||||||||||||||||||||||||||------------------------------|||||||||||||||||---------------------------------------------------||-----|||||||||||||||||||||||||------||------||||||||||||||||||---------------------|||||-------------------||----------||------------------------------|||||--------||||||-----------|||||||||||||||||||-----|||||||----||||-----||||--------------|||---|||-----------------------|||||||||||||||||||||||--------|||||||||||--||||----------------||||||||||||||||--|||---|||||||||----|||||||||||------||||||||||||||------||||-||||----||||||----|||||||||||------|||-----|||||||||||||||||-----------|||||||||------|||||||||||||||||||||------------|||||||||||||||||||--|||||||||||||||--|||||||||||||||||||||||||||||||||||||||||||||||||-|||||-||||||||||||||||||||||--|---------||------------------------||----||||||---|||||----||||||||||||||----|||||||||||||||||||------||||||--||||||||||||--||||||||||||||||||---||||||-------------|||----|||||--||||-------||||----||----||----||----||------||||||||||----||------|||||||----------------|-----|||||--||||---||------|||||||||--||||------||-----||||------||||||||-----------------||--|||||||||||||||||||||||||||----------------------|||||||------||||||||||----||||----|||||||||||||||||||||||------||||---------------||||||||----------------------||||||--||||----------------------||---||||----|||||||||||||----||||||----||||||||||--------||||||||||||||||||||||||||||||||||||||||||||||||||||||||||-------||||||||-----------||||||||||||||||||||||||||||||||||||||";
System.out.println(str.length());
// 프로그램에 종료
// System.exit(0);
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i <1000; i++) {
System.out.print("+");
}
}
});
t4.start();
// 람다 활용
new Thread(() -> {
for(int i=0; i<1000; i++) {
System.out.print("!");
}
}).start();
}
}
// Runnable 인터페이스 구현
class MyClass implements Runnable {
public void run() {
for(int i=0; i<1000; i++) {
System.out.print("*");
}
}
}
2. 스레드 우선순위
- 중간:5(기본값), 낮음:1, 높음:10
- 작업의 중요도에 따라 스레드의 우선순위를 서로 다르게 지정하여 특정 스레드가 더 많은 작업시간을 갖도록 할 수 있는 것
예제) 스레드의 우선순위 적용방법 ( 위 예제 추가)
t4.start();
t4.setPriority(6);
3. 스레드 상태 제어
https://link2me.tistory.com/1730
위 링크 스레드생명주기 표 참고
https://vmilsh.tistory.com/374
위 링크 운영체제 생명주기 표 참고
JVM이 main의 호출컵을 만들고 제일 아래에 main을 호출
*운영체제 생명주기
ready에서 일을 하려고 일렬로 기다리다 순서대로 running 을 한다. 일이 다 끝나면 terminated로 가고 밀려나게 되면 ready 혹은 sleep으로 가게된다.
sleep은 외압에 의해 강제로 종료되었음을 의미한다.
sleep에 대한 예제) 위 예제에서 sleep 추가
package chapter17;
import java.io.IOException;
import java.nio.CharBuffer;
// Thread클래스 상속
public class ThreadEx extends Thread {
// 이 프로그램은 총 3개의 스레드가 동작한다 (메인1 메인밑2)
public void run() {
for(int i=0; i < 1000; i++) {
System.out.print(getName()); // getName은 스레드 클레스가 가지고있는 메서드
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new ThreadEx();
// 스레드 이름 "-"
t1.setName("-");
Thread t2 = new ThreadEx();
// 스레드 이름 "|"
t2.setName("|");
t1.start();
t2.start();
Thread t3 = new Thread(new MyClass());
t3.start();
// 순서대로 처리 스레드와는 다름
// t1.run();
// t2.run();
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i <1000; i++) {
System.out.print("+");
}
}
});
t4.start();
t4.setPriority(6);
// 람다 활용
new Thread(() -> {
for(int i=0; i<1000; i++) {
System.out.print("!");
}
}).start();
for(int i=0; i<5; i++) {
System.out.println("main!!!!!!");
sleep(1000);
}
String str = "-----||||||||||-----------------------------|||||||||||||||||||||||||||-------------------------------------------------------|-----------------|||||||||||||---------------------------------------------------------------------------------------------------------------------------------------||||||||||||----------------|||||||||||||----------------------|||||||||||||||||||||||---||||||||||||||||||||||||||||||||||--------------------||||||||||||||||----------||||||||||||||||||||||||||||||||||||||||||||------------------------------|||||||||||||||||---------------------------------------------------||-----|||||||||||||||||||||||||------||------||||||||||||||||||---------------------|||||-------------------||----------||------------------------------|||||--------||||||-----------|||||||||||||||||||-----|||||||----||||-----||||--------------|||---|||-----------------------|||||||||||||||||||||||--------|||||||||||--||||----------------||||||||||||||||--|||---|||||||||----|||||||||||------||||||||||||||------||||-||||----||||||----|||||||||||------|||-----|||||||||||||||||-----------|||||||||------|||||||||||||||||||||------------|||||||||||||||||||--|||||||||||||||--|||||||||||||||||||||||||||||||||||||||||||||||||-|||||-||||||||||||||||||||||--|---------||------------------------||----||||||---|||||----||||||||||||||----|||||||||||||||||||------||||||--||||||||||||--||||||||||||||||||---||||||-------------|||----|||||--||||-------||||----||----||----||----||------||||||||||----||------|||||||----------------|-----|||||--||||---||------|||||||||--||||------||-----||||------||||||||-----------------||--|||||||||||||||||||||||||||----------------------|||||||------||||||||||----||||----|||||||||||||||||||||||------||||---------------||||||||----------------------||||||--||||----------------------||---||||----|||||||||||||----||||||----||||||||||--------||||||||||||||||||||||||||||||||||||||||||||||||||||||||||-------||||||||-----------||||||||||||||||||||||||||||||||||||||";
System.out.println(str.length());
// 프로그램에 종료
// System.exit(0);
}
}
// Runnable 인터페이스 구현
class MyClass implements Runnable {
public void run() {
for(int i=0; i<1000; i++) {
System.out.print("*");
}
}
}
'JAVA' 카테고리의 다른 글
23-07-12 JAVA / Spring Bean Life Cycle (0) | 2023.07.12 |
---|---|
23-07-10 객체 지향 프로그래밍 (OOP / Object-Oriented Programming) (0) | 2023.07.10 |
23-02-02(2) JAVA (set인터페이스, Hash, Tree) (0) | 2023.02.02 |
23-02-01(2) JAVA (Calender클래스, DecimalFormat 클래스, SimpleDateFormat, 컬렉션 프레임워크, List 인터페이스) (0) | 2023.02.01 |
23-01-31 (2) JAVA (StringBuffer, Math 클래스, Wrapper 클래스 (0) | 2023.01.31 |