JAVA

JAVA 쓰레드

짱코딩러 2022. 7. 29. 17:18

프로세스 : 실행중인 프로그램(공장)

쓰레드 : 프로세스 내에서 작업을 수행(일꾼)

 

쓰레드의 구현

*ThreadEx1_2는 Thread를 상속받지 않았기 때문에 Thread가 아니다.

 Thread를 생성하고, 해당 생성자에 MyThread2를 넣어서 Thread를 생성한다.*

class Ex13_1 {
	public static void main(String args[]) {
		ThreadEx1_1 t1 = new ThreadEx1_1();

		Runnable r = new ThreadEx1_2();
		Thread t2 = new Thread(r);	  // 생성자 Thread(Runnable target)

		//두개의 쓰레드를 만들고 작업을 따로 돌린거임!
		//번갈아가면서 시행되는데 어떤게 얼마의 시간동안 시행될지는 OS스케줄러맘이라 알 수 없음
		t1.start();
		t2.start();
	}
}

class ThreadEx1_1 extends Thread {	//1.Thread클래스를 상속해서 쓰레드를 구현
	public void run() {	//쓰레드가 수행 할 작업을 작성
		for(int i=0; i < 5; i++) {
			System.out.println(this.getName()); //조상인 Thread의 getName()을 호출
		}					//여기서 this가 쓰레드임 
	}
}

class ThreadEx1_2 implements Runnable {	//2.Runnable인터페이스를 구현해서 쓰레드를 구현
	public void run() {
		for(int i=0; i < 5; i++) {
			// Thread.currentThread() - 현재 실행중인 Thread를 반환한다.
			System.out.println(Thread.currentThread().getName());
		}					//얘는 상속받은게 아니니까 Thread.currentThread()메소드를 이용해 getName()불러옴
	}
}

 

데몬 쓰레드

: 일반 쓰레드의 보조적인 역할을 수행(일반쓰레드가 종료되면 자동종료)

class Ex13_7 implements Runnable  {
	static boolean autoSave = false;
	//false로 시작, i==5일때 true로 바뀜

	public static void main(String[] args) {
    	//생성자를 호출할 때 Runnable 인터페이스를 구현한 클래스 객체를 넣어줘야함
		Thread t = new Thread(new Ex13_7());	//Thread(Runnable r)
		t.setDaemon(true);	//데몬쓰레드로 만듦.이 부분이 없으면 종료되지 않는다.run()을 무한루프돌게 만들었기때문
		t.start();

		for(int i=1; i <= 10; i++) {
			try{
				Thread.sleep(1000);
			} catch(InterruptedException e) {}
			System.out.println(i);

			if(i==5) autoSave = true;
		}

		System.out.println("프로그램을 종료합니다.");
	}

	public void run() {
		while(true) {
			try { 
				Thread.sleep(3 * 1000); // 3초마다
			} catch(InterruptedException e) {}

			// autoSave의 값이 true이면 autoSave()를 호출한다.
			if(autoSave) autoSave();
		}
	}

	public void autoSave() {
		System.out.println("작업파일이 자동저장되었습니다.");
	}
}

 

스레드로 라면끓이기

import java.util.Scanner;

public class RamenProgram {

	public static void main(String[] args) {
		int num;
		Scanner input = new Scanner(System.in);

		System.out.println("라면 몇 개 끓일까요?");

		num = input.nextInt();

		System.out.println(num + "개 주문 완료! 조리시작!");
		try {
			RamenCook ramenCook = new RamenCook(num);
			//4개의 스레드 생성
			new Thread(ramenCook, "A").start();
			new Thread(ramenCook, "B").start();
			new Thread(ramenCook, "C").start();
			new Thread(ramenCook, "D").start();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

interface Runnable {
	public void run();
}

class currentThread extends Thread {
	public RamenCook ramenCook;
	static String nam;

	currentThread() {
		this(new RamenCook(5), "");
	}

	currentThread(RamenCook ramenCook, String nam) {
		this.ramenCook = ramenCook;
		this.nam = nam;
	}
}

class RamenCook extends Thread implements Runnable {
	private int ramenCount;	//끓여야 할 라면의 수
	private String[] burners = { "_", "_", "_", "_" };	//각 버너(비어잇는)

	public RamenCook(int count) {	//1.끓일 라면의 갯수를 받아서 변수에 저장
		ramenCount = count;
	}

	@Override
	public void run() {	//스레드에서 진행할 작업을 정의하는 곳
		while (ramenCount > 0) {	//더 끓일 라면의 수가 0이 될때까지 반복
			 //얘는 한번에 한 스레드만 건들 수 있음
			synchronized (this) {//스래드 두개가 동시에 라면 가져가도 하나만 줄어드는 상황이 생기는걸 방지
				ramenCount--;  //2.라면을 가져가서 갯수를 하나씩 줄임
				System.out.println(Thread.currentThread().getName() + " : " + ramenCount + "개 남았습니다");
			}

			for (int i = 0; i < burners.length; i++) {	//3-2.빈 버너를 찾아
				if (!burners[i].equals("_")) {
					continue;
				}

				synchronized (this) {	//둘 이상의 스레드가 한 버너를 차지하지 못하게 방지
					// if(burners[i].equals("_"))
					// {
					burners[i] = Thread.currentThread().getName();	//3.냄비올려(버너를 해당스레드의 이름으로 변경)
					System.out.println(
							"                 " + Thread.currentThread().getName() + " : [" + (i + 1) + "]번 버너 ON");
					showBurners();	//버너 보여쭹
					// }
				}

				try {
					Thread.sleep(3000);	//4.스레드를 2초동안 정지(라면 끓이는중^^~)
				} catch (Exception e) {
					e.printStackTrace();
				}

				synchronized (this) {
					burners[i] = "_";	//5.다 끓이고 나면 버너를 비움
					System.out.println("                                  " + Thread.currentThread().getName() + " : ["
							+ (i + 1) + "]번 버너 OFF");
					showBurners(); //버너 보여줘
				}
				break;
			}

			try {
				//스레드마다 다음 라면을 끓이기까지 랜덤으로(0~1초) 정지되도록 함(순서 섞이라고)
				Thread.sleep(Math.round(1000 * Math.random()));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private void showBurners() {	//실행되는 시점마다 버너의 상태를 출력 
		String stringToPrint = "                                                             ";
		for (int i = 0; i < burners.length; i++) {
			stringToPrint += (" " + burners[i]);
		}
		System.out.println(stringToPrint);
	}

}

'JAVA' 카테고리의 다른 글

JDBC 한번에 여러개 처리 addBatch, executeBatch  (0) 2022.10.06
JAVA 싱글톤(Singleton)  (0) 2022.08.17
JAVA 컬렉션 프레임웍 List Set Map  (0) 2022.07.29
JAVA Calendar  (0) 2022.07.26
JAVA 생성자  (0) 2022.07.23