Process: thread의 집합으로 하나의 exe, com, dll 프로그램을 말합니다.
현재 실행되고 있는 프로그램입니다.
Process간 자원(memory)을 공유할 수 없습니다. 따라서 Process를 많이 발생 시키면 자원이 바닥나게 됩니다.
Thread:
독립된 작은 실행단위로 프로세스를 구성합니다.
반복적으로 동기화하여 실행되는 프로그램 루틴 입니다.
메소드(함수)단위의 처리 모듈, process의 구성 요소입니다.
Thread는 많이 발생해도 자원을 공유함으로 Process에 비해 시스템에 적은 부담이 됩니다.
각각의 Thread는 자신의 일을 하고 있으며, 동시에 실행되지 않습니다.
스레드 스케줄러에 의해서 스레드의 여러상태중 실행상태로 변경할 수 있습니다.
스레드의 상태는 준비상태, 실행상태, 대기상태, 정지상태가 있습니다.
스레드는 자원을 공유하는 특징이 있어 멤버필드와 static 필드를 공유합니다.
Handle: 메모리 포인터, 함수포인터등의 핸들러, thread의 구성요소입니다.
run()메소드안에 처리로직을 구현하거나 처리로직을 호출하는 로직이 구현되어 있어야 합니다.
네크워크, 게임, 데이터베이스, 웹 관련 프로그램에서 많이 사용
자바의 스레드는 많은 Reference 참조로 인해 C언어의 스레드보다 속도 및 안정성이 떨어져 접속자가 많은 네트워크 관련 프로그램에는 사용을 하지 않습니다.
Hash Code 관리 부분에 많은 리소스가 소모됩니다.
스레드 콜백 메소드와 기본 메소드
start(): . 스레드를 스레드 스케쥴러에 등록하고 실행상태로 변경합니다. . 이 메소드를 실행했다고해서 바로 스레드가 실행이 되는 것은 아닙니다. . JVM은 스레드를 실행할 수 있는 여유가 생겼을 때 자신이 작성한 스레드 스케쥴러에 의해서 스레드의 run()메소드를 호출합니다.
run(): JVM이 호출하는 콜백메소드로 여기서 콜백 메소드는 개발자가 호출을 코드상에 지시하는 것이 아니라 JVM이 호출하는 메소드를 말하는 것으로 이 run()메소드 안에는 스레드 상태에서 처리하려고 하는 모든 비즈니스 로직이 구현되어 있어야 합니다. 가장 중요한 메소드입니다.
sleep(long milli second): 지정된 시간동안 스레드를 쉬게하고, 그 시간이 지나면 다시 스레드가 작동됩니다. . 1000이 1초입니다.
wait(): 현재를 스레드 무한정 대기 시킵니다. notify(), notifyall()메소드를 통해서 재 실행 가능합니다.
suspend():스레드의 실행을 일시적으로 중단 시킵니다. 다시 실행은 resume()를 통해서만 가능합니다.
yield(): 스레드의 실행 권한을 무조건 다른 스레드에게 넘겨 줍니다.(양보)
stop(): 스레드 실행을 완전히 종료 합니다.
getName(): 쓰레드의 이름을 알려줍니다.
Thread.currentThread()는 현재 실행중인 쓰레드를 알려줍니다.
단일 스레드
일반적으로 하나의 자바 프로그램을 만들어 실행하면 단일 스레드 상태가 됩니다.
main()메소드가 대표적인 단일 스레드입니다.
멀티 스레드
멀티 스레드는 하나의 메소드가 처리가 끝나는 것이 아니라 여러 메소드가 계속적으로 실행상태에 있으면서 자원을 공유하고 이용하는 처리 형태를 말합니다.
어느 한 메소드가 실행이 종료 되지 않고 다른 메소드와 함께 계속 실행상태에 있게 되는 것
스레드의 생성 방법
Thread 클래스를 상속받는 방법
Runnable 인터페이스를 구현하는 방법
자바는 다중 상속이 안됨으로 클래스가 특정 클래스를 상속할 필요가 있는 경우는 반드시 Runnable인터페이스를 구현해야 합니다.
스레드 실습
스레드를 이용하지 않은 경우
GenClass
class GenClass{
private int num;
private String name;
public GenClass(String a, int b){ //생성자
name = a;
num = b;
}
public void start(){
for(int i=0; i<num; i++)
System.out.println(name + " : " + i);
}
}
NonThread.java
public class NonThread{
public static void main(String args[]) {
GenClass t1 = new GenClass("first", 5);
GenClass t2 = new GenClass("second", 5);
GenClass t3 = new GenClass("third", 5);
t1.start();
t2.start();
t3.start();
}
}
Thread 클래스를 상속받은 경우
start() ---> JVM ---> run()
start(): 개발자: 스레드 스케쥴러에 등록
run(): JVM이 스레드스케쥴러를 확인후 그 실행 순서에 따라 run()메소드를 호출함, CallBack Method에 해당됨
CallBack Method: JVM이 자신의 실행 스케쥴러를 만들고 거기에 등록된 순서에 따라 자동으로 호출하는 메소드
class MyThread extends Thread{
private int num;
private String name;
public MyThread(String a, int b) {
name = a;
num = b;
}
public void run() { //Callback 메소드
for(int i=0; i<num; i++)
System.out.println(name + " : " + i);
}
}
ThreadTest1.java
public class ThreadTest1{
public static void main(String args[]) {
MyThread t1 = new MyThread("first", 1000);
MyThread t2 = new MyThread("second", 1000);
MyThread t3 = new MyThread("third", 1000);
t1.start();
t2.start();
t3.start();
}
}
Runnable 인터페이스를 사용한 경우
스레드 내용을 가지고 있는 클래스가 추가적인 기능이 필요해 다른 클래스를 상속받는 경우는 Thread 클래스를 Extend 할 수 없음으로 반드시 Runnable 인터페이스를 상속받아야 합니다.
상속을 받으면서 스레드를 구현하고 싶은 경우 사용됩니다.
ThreadOne.java
class ThreadOne implements Runnable {
private int num;
private String name;
public ThreadOne(String a, int b) {
name = a;
num = b;
}
public void run(){
for(int i=0; i<num; i++)
System.out.println(name + " : " + i);
}
}
ThreadTest2
public class ThreadTest2{
public static void main(String args[]) {
//Runnable Interface를 구현한 클래스 객체를
//Thread 클래스의 생성자로 할당합니다.
Thread t1 = new Thread(new ThreadOne("first", 1000));
Thread t2 = new Thread(new ThreadOne("second", 1000));
Thread t3 = new Thread(new ThreadOne("third", 1000));
t1.start();
t2.start();
t3.start();
}
}
setPriority(int p): 현재 스레드의 우선순위를 인자 p로 설정하기 위한 메소드
getPriority(): 현재 스레드의 우선순위를 반환하는 메소드
sleep()를 적용한 경우
특정 스레드에 CPU의 자원이 집중하는 것을 막을 수 있습니다.
불규칙적인 동기화는 지원합니다.
RunThread2.java
class RunThread2 extends Thread {
public RunThread2(String name) {
super(name);
}
public void run() {
for ( int i = 1; i <= 30000000 ; i++ ) {
if ( i % 50 == 0 ){
System.out.println("Thread [" + getName() + "] : " + i);
try{
//sleep(1); //0.001초
System.out.print("");
}catch(Exception e){ }
}
}
}
}
SchedulingTest2.java
public class SchedulingTest2 {
public static void main(String args[]) {
Thread[] t = new RunThread2[5];
t[0] = new RunThread2("☆");
t[1] = new RunThread2("★");
t[2] = new RunThread2("◆");
t[3] = new RunThread2("◇");
t[4] = new RunThread2("○");
t[0].start();
t[1].start();
t[2].start();
t[3].start();
t[4].start();
}
}
우선순위를 적용한 예
Thread.MAX_PRIORITY 10
Thread.NORM_PRIORITY 5
Thread.MIN_PRIORITY 1
sleep()의 이용, 우선순위가 적용은 되나 다른 스레드에게 제어권이 자주 넘어감
RunThread4.java
class RunThread4 extends Thread {
public RunThread4(String name) {
super(name);
}
public void run() {
for ( int i = 1; i <= 10000 ; i++ ) {
if ( i % 50 == 0 )
System.out.println("Thread [" + getName() + "] : " + i);
try{
sleep(1); //0.001초
}catch(InterruptedException e){ }
}
}
}