스레드(Thread)

Cjw.dev·2023년 3월 2일

스레드

프로세스 내에서 실제로 작업을 수행하는 주체
-> 일련의 코드의 실행 흐름

모든 프로세스에는 최소 1개 이상의 스레드가 존재하여 작업을 수행하며 두개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스라 부른다

프로세스 : 실행중인 프로그램.

  • 사용자가 작성한 프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행중인 것
  • 프로세스는 프로그램에 사용되는 데이터 + 지원 + 스레드의 집합으로 구성

프로그램

  • 하나 혹은 그 이상의 프로세스로 운영될 수 있음
  • 하나의 프로세스는 하나 또는 그 이상의 스레드로 운영될 수 있음


<프로그램 프로세스 스레드의 관계>

스레드를 이해해보자

package thread;

public class threadExam {

	public static void main(String[] args) {
		//하나의 스레드로 0부터 10억까지의 짝수를 더하는 프로그램
		
		long startTime = System.currentTimeMillis();
		long sum=0;
		
		for(long i=0; i<=2000000000; i++) {
			if(i%2==0) {
				sum+=1;
			}
		}
		System.out.println(sum);
		long endTime = System.currentTimeMillis();
		System.out.println("걸린시간 : " + (endTime - startTime) + "m/s");
	}

}
결과값:
1000000001
걸린시간 : 1743m/s

스레드의 생성과 실행
스레드의 생성자는 Runnable 인터페이스를 구현한 객체만 전달가능
스레드는 에러가 많이 나기 때문에 try~catch (예외처리) 해야한다.

start메소드가 호출이 되면 Runnable의 run 메소드를 실행
-> 오버라이딩된 메소드가 있다면 오버라이딩된 run메소드를 실행

package thread;

public class threadExam implements Runnable{

	public long sum = 0;
	private final long from;
	private final long to;
	
	public threadExam(long from, long to) {
		this.from = from;
		this.to = to;
	}
	
	public static void useThread() {
		try {
			long startTime = System.currentTimeMillis();
			long sum =0;
			// 메인스레드가 A스레드, B스레드에게 작업 실행 명령
			// A는 0~10억, B는 10억1~20억까지
			// 최종적으로 두 스레드의 작업이 끝나면 결과를 가져와 합치면 짝수의 합을 뽑을 수 있다.
			threadExam th1 = new threadExam(0,1000000000); // 
			Thread threadA = new Thread(th1);
			threadExam th2 = new threadExam(1000000001,2000000000);
			Thread threadB = new Thread(th2);
			
			threadA.start();
			threadB.start();
			threadA.join();  // 호출하는 스레드를 기다리는 메소드. A 끝나면 B 실행
			threadB.join(); // 
		
			System.out.println(th1.sum + th2.sum);
			long endTime = System.currentTimeMillis();
			System.out.println("걸린시간 : " + (endTime - startTime) + "m/s");

		} catch (InterruptedException e) {
			// TODO: handle exception
		}
	}
		
	
	public static void notUseThread() {
		long startTime = System.currentTimeMillis();
		long sum =0;
		for(long i = 0; i<=2000000000; i++) {
			if(i%2==0) {
				sum+=i;
			}
		}
		System.out.println(sum);
		long endTime = System.currentTimeMillis();
		System.out.println("걸린 시간 : " + (endTime- startTime));
	}
	
	
	@Override
	public void run() {
		for(long i=0; i<=1000000000; i++) {
			if(i%2==0) {
				sum+=1;
			}
		}
	}
	
	public static void main(String[] args) {
		//하나의 스레드로 0부터 10억까지의 짝수를 더하는 프로그램
		notUseThread();
//		useThread();
	}
}

싱글 스레드와 멀티스레드 차이

<싱글스레드>

package thread;

import java.awt.Toolkit;

public class BeepPrint {

	public static void main(String[] args) {
		
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		
		for(int i=0; i<5; i++) {
			System.out.println("스레드명" + Thread.currentThread().getName());
			toolkit.beep();
			
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}//for문 end
		
		for(int i=0; i<5; i++) {
			System.out.println("스레드명" + Thread.currentThread().getName());
			System.out.println("띠요옹");
			
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

<멀티스레드>

package thread;
   public class BeepMultiMain {
    public static void main(String[] args) {
		
		// 멀티스레드 구현방법
		
		Runnable runnable = new Beep();
		Thread thread = new Thread(runnable);
		

		for(int i=0; i<5; i++) {
			System.out.println("스레드명" + Thread.currentThread().getName());
			System.out.println("띠요옹");
			
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
package thread;

import java.awt.Toolkit;

	public class Beep implements Runnable{
	@Override
	public void run() {
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		for(int i=0; i<5; i++) {
			System.out.println("스레드명" + Thread.currentThread().getName());
			toolkit.beep();
			
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}//for문 end
	}
	
}
//결과 : 
스레드명main
띠요옹
스레드명main
띠요옹
스레드명main
띠요옹
스레드명main
띠요옹
스레드명main
띠요옹
// 메인에서 먼저 스레드명main+띠요옹 출력 후 비프음 발생. 
// 동시에 실행되니  멀티스레드를 쓰면 10초 걸리던 것이 5초로 단축 됨.

메인 스레드

자바 프로그램이 실행될 때 Main메소드를 거치면서 시작한다. 그 때 실행되는 스레드(무조건 싱행)
메인 스레드가 스레드(작업 스레드)를 만들어 코드를 병렬로 실행

작업 스레드 생성과 실행

몇 개의 작업을 병렬로 실행할지 설계단에서 결정할 필요가 있음

데몬스레드(DeamonThread)

메인스레드가 종료되면 서브스레드(멀티,작업스레드)의 작업이 끝나지 않았더라도 같이 종료되는 스레드

package thread;

public class FastRun implements Runnable{

	public String name;
	

	public FastRun(String name) {
		this.name = name;
	}
	@Override
	public void run() {
		int sum=0;
		for(int i=0; i<10000; i++) {
			sum+=i;
		}
		System.out.println(name + ":" + sum);
	}

}
package thread;

public class DaemonThreadExam {

	public static void main(String[] args) {
		
		Thread threadA = new Thread(new FastRun("김규동"));
		threadA.setDaemon(true); // 해당 스레드를 데몬 스레드로 변경
		Thread threadB = new Thread(new FastRun("조원재"));
		threadB.setDaemon(true);

		threadA.start();
		threadB.start();
		System.out.println("팀장님 퇴근함 오예!");
		
	}

} //결과 : 메인 스레드 작업 종료시, 김규동, 조원재도 같이 작업 종료됨. 
profile
백엔드 개발 공부 기록 22.11.07 ~ ing

0개의 댓글