상세 컨텐츠

본문 제목

JAVA Thread run() start()

BackEnd/JAVA

by H_Develop 2022. 8. 1. 17:28

본문

독립적인 프로세스 실행단위.

한 번에 두 가지 이상의 프로세스(운영체제에서 실행중인 하나의 프로그램)을 실행 가능하게 해준다.

실제로 동시에 두 개가 실행되는 것은 X.

운영체제 내부에서 CPU의 프로세스를 쪼개서 각각 Time Slot에 넣고 번갈아 실행하는 것이다.

동시에 돌아가는 것처럼 보이도록 아주 빠르게 번갈아서 스레드 실행이 되는 것인데 사람은 느끼지 못한다.

 

//Single Thread

class ThreadEx extends Thread { //내장되어 있는 Thread를 상속
    @Override
    public void run(){
        for(int i=0; i<=10; i++)
        {
            System.out.println("Thread activation");
        }
    }
}

public class Test07 {
    public static void main(String[] args) {
        ThreadEx t = new ThreadEx(); 
        t.run(); //t.start()를 사용하여 병령 쓰레드를 실행시킬 수 있다.
        System.out.println("End of Main class");
     
    }
}

 

쓰레스 실행 함수.run() 순서대로 나오는 함수start() 병렬처리되는 함수 - sleep() 는 try - catch 를 사용해야 한다.

 

class Thread_mul1 extends Thread{
	@Override
	public void run() {
		for (int i=0; i<=50; i++) {
			System.out.print("1");
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {               
                e.printStackTrace();
            }
		}
	}
}
class Thread_mul2 extends Thread{
	@Override
	public void run() {
		for (int i=0; i<=50; i++) {
			System.out.print("2");
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {      
                e.printStackTrace();
            }
		}
	}
}
public class App {
	
	public static void main(String[] args) {
		// Thread_mul1 ts = new Thread_mul1();
		// Thread_mul2 as = new Thread_mul2();

		// ts.run(); 
		// as.run();

		Thread_mul1 mt1 = new Thread_mul1();
		Thread_mul2 mt2 = new Thread_mul2();

		mt1.start();
		mt2.start();
	}
}

 

class Thread_Ex extends Thread {
	private int[] temp;
	public Thread_Ex() { // 생성자
		temp = new int[10];
		// 이 클래스 밖에서 이를 이용한 생성자 생성은 Thread_Ex temp = new Thread_Ex(),
		// temp.run/start() 이런 식으로 처리했어야 한다.
		for (int i = 0; i < temp.length; i++) {
			temp[i] = i;
		}
	}
	public void run() {
		for (int i : temp) {
			// 확장 for문 : temp에 데이터가 있는 동안
			try {
				Thread.sleep(1000); // 1초 대기
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println("temp: " + temp[i]);
		}
	}
}
public class Test02 {
	public static void main(String[] args) {
		Thread_Ex te1 = new Thread_Ex();
		te1.run();
		// 멀티 처리를 위한 start()를 호출하면 단일 처리를 해주는 run()도 실행된다.
		try {
			Thread.sleep(2000); // 2초
			System.out.println("프로그램 종료");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Thread Class (java.lang.Thread;)에는 많은 메써드가 있는데, 그 중 단일 쓰레드는 run()를 사용하고,멀티 쓰레드는 start()를 오버라이드해서 사용할 수 있는데, start() 내부적으로 run()도 실행된다.

 

 시차 주기object.sleep(sec); 주어서 두 쓰레드 사이에 격차를 주고, 실행시키기도 한다. - Thread class와 동일한 개념으로 사용될 수 있는 것으로 Runnable interface를 사용할 수 있다.

class Thread_Ex extends Thread {...} 를

class Runnable_Ex implements Runnable { ...} 식으로 변경해주면 된다.

이 Runnable Interface 에서는 단일 쓰레드만 빠르게 취급하므로 run() 하나만 사용하면 된다.

start()를 사용한다면, 객체를 생성해서 사용하면 된다.

 

class Runnable_Ex implements Runnable {...} Interface

Runnable interface는 재사용성이 높다. (일단, Thread class를 상속받으면 다른 클래스를 상속받기 어렵기에

여러 클래스를 쉽게 상속받을 수 있는 인터페이스가 좋을 수 있다.)

Runnable 코드의 일관성을 유지할 수 있어서 일부 수행에서는 Thread 보다 더 효율적일 수 있다.

run() 을 호출하는 것은 생성된 쓰레드를 실행하는 것이 아니라 클래스의 메서드를 실행하는 것이지만,

Start()를 사용하면 실행에 필요한 스택(stack:메모리)를 확보한 뒤, run()을 각각 호출해서 사용하기 때문에 멀티 쓰레드가 가능한 것 이다.

 

class Thread_ex2 implements Runnable {//class Thread_ex2 extends Thread
	int temp[];
	public Thread_ex2(){
		temp = new int[10];
		for (int i = 0; i < temp.length; i++) {
			temp[i] = i;
		}
	}
	public void run(){
		for(int i =0; i<temp.length; i++){
			try{
				Thread.sleep(1000);
			}catch(Exception e){
				e.printStackTrace();
			}
			System.out.println("temp: " + temp[i]);
		}
	}
}
public class Test03 {
	public static void main(String[] args) {
		Thread_ex2 te1 = new Thread_ex2();
		Thread te2 = new Thread(te1); //Thead_ex2 te2 = new Thread_ex2();
		te2.start();
	}
}

 

public class Test04 implements Runnable {

	@Override
	public void run() {	
				System.out.println("run");
				first();
	}
	public void first(){
		System.out.println("first");
		second();
	}
	public void second(){
		System.out.println("second");
	}
	public static void main(String[] args) {
		System.out.println("Starting main class");
		Test04 tt1 = new Test04();
		Thread tt2 = new Thread(tt1);
		tt2.start();
        // try {
		// 	Thread.sleep(1);
		// } catch (Exception e) {
		// 	e.printStackTrace();
		// }
		System.out.println("Ending main class");
	}	
}

Starting main class
Ending main class
run
first
second

 

run()를 쓰면,

Starting main class
run
first
second
Ending main class

 

결과를 보면, ' 메인 클래스 시작 ' > run() > first() > second() > ' 메인 클래스 종료 '

순으로 나와야 할 것 같지만 실제로 그렇지 않다.

' 메인 클래스 시작 ' 한 뒤, start()를 호출하기에 run()로 실행되고, first(), second(), main class로 와서 ' 메인 클래스 끝 ' 을 보여야 하지만,

' 메인 클래스 시작 ' > ' 메인 클래스 종료 ' > run() > first() > second() 이렇게 출력이 된다.

메인 클래스가 실행된 이후에, Thread 객체를 호출하고, start()를 사용해 run()를 호출했지만 run()가 호출되기 전에 그 아래 줄인 ' 메인 클래스 종료 ' 가 먼저 출력되었기 때문이다.

 - 이처럼 Thread 를 사용하면, ' 위에서 아래로, 좌에서 우 ' 로 라고 하는 작업순서를 따르게 되지 않을 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

관련글 더보기