Thread



  • Thread


1. Thread


직렬적인 프로세스의 처리 순서를 정하지 않고 동시에 실행시켜 “병렬적”으로 실행한다

자바의 쓰레드를 이용하여 하나의 프로세스에서 여러 루틴을 가지고 동시에 실행 할 수 있다


1.1 Thread 클래스의 상속


Thread 클래스를 상속받아 Thread를 구현하는 방법 run()메서드를 오버라이딩하여 main에서 start()메서드 통해 구현

public class Ex2_ThreadTest {

	public static void main(String[] args) {

		MakeCar1 mc1 = new MakeCar1("차틀 만들기");
//		mc1.run();
		mc1.start(); // start() 호출 -> run() 호출됨

		MakeCar1 mc2 = new MakeCar1("도색");
//		mc2.run();
		mc2.start();

		System.out.println("프로그램 끝");
	}

}

class MakeCar1 extends Thread{	// Thread 클래스 상속

  String work;

	public MakeCar1(String work){  // 생성자
		this.work = work;
	}

	public void run() {	// run메서드 오버라이딩
		for(int i=0; i<5; i++) {
			System.out.println(work +"작업중");

			try {	// 눈으로 확인하기 위해서
				Thread.sleep(500);  // 5초내로 끝냄
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}


1.1.1 Thread Join


쓰레드 조인을 이용하여 메인메서드에서 실행시킨 쓰레드가 종료되기 전에 메인메서드가 종료되는 것을 막을 수 있다 실행시킨 쓰레드가 동작이 끝날 때 까지 기다린다

import java.util.ArrayList;
import java.util.Random;
public class ThreadTest extends Thread {
	// index 변수를 추가해서 스레드가 동작시에 해당 변수를 증가시키도록 할겁니다.
	private static int index = 0;

	private int id = -1;
	public ThreadTest(int id){
		this.id = id;
	}
	public void run(){
		System.out.println( id + "번 쓰레드 동작 중..." );
		Random r = new Random(System.currentTimeMillis());
		try {
			long s = r.nextInt(3000); // 3초내로 끝내자.
			Thread.sleep(s); // 쓰레드를 잠시 멈춤
			index++; // index 변수를 증가시킵니다.
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println( id + "번 쓰레드 동작 종료..." );
	}

	public static void main(String[] args) {

		System.out.println("Start main method.");

		ArrayList<Thread> threadList = new ArrayList<Thread>();

		for(int i = 0 ; i < 10 ; i++ ){
			ThreadTest test = new ThreadTest(i);

			test.start(); // 이 메소드를 실행하면 Thread 내의 run()을 수행한다.
			threadList.add(test); // 생성한 쓰레드를 리스트에 삽입
		}

		for(int i = 0 ; i < threadList.size(); i++){
			try {
				threadList.get(i).join(); // 쓰레드의 처리가 끝날때까지 기다립니다
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		System.out.println("current Index: "+ index); // index의 값을 반환합니다.
		System.out.println("End main method.");
	}
}

// 코드출처 : https://jdm.kr/blog/69


1.1.2 Thread Synchronized


쓰레드 간의 공통으로 사용하는 객체를 동기화하는방법 동기화된 객체는 쓰레드간의 동시접근이 불가능하다 synchronized => lock

import java.util.ArrayList;
import java.util.Random;
public class ThreadTest extends Thread {

	private static int index = 0;

	private int id = -1;
	public ThreadTest(int id){
		this.id = id;
	}
	public void run(){
		System.out.println( id + "번 쓰레드 동작 중..." );
		Random r = new Random(System.currentTimeMillis());
		try {
			long s = r.nextInt(3000); // 3초내로 끝내자.
			Thread.sleep(s); // 쓰레드를 잠시 멈춤
			setIndex();  // 메서드 추가
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println( id + "번 쓰레드 동작 종료..." );
	}

	public synchronized static void setIndex(){  // 쓰레드간의 객체 동기화 위한 synchronized method
		index++; // index 변수를 증가시킵니다.
	}

	public static void main(String[] args) {

		System.out.println("Start main method.");

		ArrayList<Thread> threadList = new ArrayList<Thread>();

		for(int i = 0 ; i < 10 ; i++ ){
			ThreadTest test = new ThreadTest(i);

			test.start(); // 이 메소드를 실행하면 Thread 내의 run()을 수행한다.
			threadList.add(test); // 생성한 쓰레드를 리스트에 삽입	=> ArrayList에 쓰레드의 주소를 순서대로 넣는다 ?
		}

		for(int i = 0 ; i < threadList.size(); i++){
			try {
				threadList.get(i).join(); 	// ArrayList에서 순서대로 뽑아와서 실행시킨다 // join에 의해 차례대로 실행됨
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		System.out.println("current Index: "+ index); // index의 값을 반환합니다.
		System.out.println("End main method.");
	}
}

//코드출처 https://jdm.kr/blog/69


class Count {

	int i;

	synchronized void increment() {	// 첫번째 쓰레드가 접근해서 첫번째 작업을 끝낼때까지 다른 쓰레드가 접근 못함
		i++;
	}

	/* void increment(){	// 메서드의 내용이 길 경우 synchronized를 위에처럼 붙여버리면 너무 느려짐 따라서 필요한 부분에만 synchronized 붙일수 있음
	 * 	synchronized(this){ // 단, 공유할 객체를 물고 들어가야함 없으면 자기자신(this)
	 * 		i++;
	 * 	}
	 *}
	 */

}

class ThreadCount extends Thread{
	Count cnt;

	public ThreadCount(Count cnt) {  // 생성자
		this.cnt = cnt;
	}

	public void run() {  // run 오버라이딩
		for(int i=0; i<100000000; i++) {
			cnt.increment();
		}
	}
}

public class Ex7_Synch {

	public static void main(String[] args) {
		Count cnt = new Count();

		ThreadCount tc1 = new ThreadCount(cnt);
		tc1.start();

		ThreadCount tc2 = new ThreadCount(cnt);
		tc2.start();

		// join() 통해서 쓰레드가 끝날때가지 기다림		// 이 경우 i를 서로 공유하고 있으므로 원하는 결과 안나옴 따라서 자원공유하면서 쓰레드 하기위해서는-> i에 lock걸어줘야 함	//
		try {
			tc1.join();	// tc1이 끝날때까지 메인 못끝내게
			tc2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("i값 =="+cnt.i);
	}

}