스퐁지송 개발노트

22.12.06(화) Thread 본문

JAVA 입문 시작

22.12.06(화) Thread

강준석 2022. 12. 6. 11:39
728x90

Thread 

1.Tread 클래스를 만든후 Main클래스에서 상속시켜 사용 [ ex) 클래스명 extends Thread ]

2.위에서 아래로 순차적으로 식을 처리하는 것이아닌 처리공간을 동시에 만들어 동시에 식을 처리

3.익명 구현 객체를 사용 (익명 구현 객체랑)

4.람다식을 활용

5.Runnable자바기본 인터페이스를 구현하면

run 메서드를 구현해야함  public void run()  
                                                               


예시

 

package 스레드;

public class ThreadExtend extends Thread{
			//run메서드는 고정
	public void run() {
		System.out.println("Thread 상속");
		for(int i =0; i<50;i++) {
			System.out.println("Thread : "+ i);
		}
	}
	
}

러너블

package 스레드;
						//인터페이스 상속받기
public class RunnableImple implements Runnable{

	public void run() {
		System.out.println("Runnable 상속");
		for(int i = 0;i<50;	i++) {
		System.out.println("Runnable : "+i);
		}
	}
	
}

메인 문

package 스레드;

public class Sample01 {

	public static void main(String[] args) {
	
		ThreadExtend t1 = new ThreadExtend();
		
		Runnable r = new RunnableImple();
		Thread t2 = new Thread(r);
		
		//같다 위의 식과
		//Thread t2 = new Thread(Runnable r = new RunnableImple(););
		
		t1.start();
		t2.start(); //t2(Thread)는 따로 처리공간이 있어 순서에 상관없이 시작한다
		
		
	}

}


실행 t1과 t2의 값이 순서 상관없이 출력된다

 


 

예시 2

 

익명 구현 객채로 Thread 만들기

(메인클래스에서 바로 구현가능)

package 복습용패키지;

public class 복습1 {

	public static void main(String[] args) {

		Thread t1 = new Thread(new Runnable() {
			public void run() {
				System.out.println("t1스레드");
				for (int i = 0; i < 50; i++) {
					System.out.println("t1 : " + i);
					//t1 1~50까지 출력
				}
			}

		});

		// 위아래는 같은식 위쪽식이 더 간단한식

		Runnable r = new Runnable() {
			public void run() {
				System.out.println("t2스레드");
				for (int i = 0; i < 50; i++) {
					System.out.println("t2 : " + i);
				}
			}
		};
		Thread t2 = new Thread(r);

		t1.start();
		t2.start();		//원래라면 t1의 식이 t2보다 먼저 실행되고,	
						//t1의 식이 종료되면 t2가 실행되어야하지만
						//Thread는 순서 상관없이 구현된 식을 동시에 처리,출력

	}

}

결과는  t1(1~50) 과 t2(1~50)이 순서 상관없이 출력(동시에 출력하기때문 따라서 출력마다 다르게 섞여서 나옴)


예시 3

 

람다식으로 Thread 만들기

 

package 스레드;

public class Sample03 {
//람다식으로 스레드 만들기
	public static void main(String[] args) {

		Thread t1 = new Thread(() -> {
			System.out.println("t1스레드");
			for (int i = 0; i < 50; i++) {
				System.out.println("t1 : " + i);
			}

		});
		
		Runnable r = () -> {
			System.out.println("t2스레드");
			for (int i = 0; i < 50; i++) {
				System.out.println("t2 : " + i);
			}

		};
		
		Thread t2 = new Thread(r);
		
		t1.start();
		t2.start();
		
	}

}

 


 

처리 우선순위 설정하는 법

 

.setPriority(1~10);   // 1~10의 정수를 넣어야함 //

우선순위를 단계별로 정리 가능 더 큰 숫자가 먼저 우선순위를 가지게 됨

 

t1.setPriority(Thread.MAX_PRIORITY);  : 가장 먼저의 우선순위를 가지게 됨(10)
t2.setPriority(Thread.MIN_PRIORITY);  : 가장 나중에의 우선순위를 가지게 됨(1)

t3.setPriority(Thread.NORM_PRIORITY);  :  중간의 우선순위를 가지게 됨(5)

 

위의 람다식으로 스레드만드는 예제를 활용


Tread 에 sleep 사용하기

.sleep()이란...

처리속도에 시간의 텀을 두는 것  sleep() <= 괄호안는 1000분에 1초로 인식 1000을 입력하면 1초의 텀이 생김 

 

Thread.sleep(1000); 작성 후 (저렇게 입력하면 오류가뜸) -> 오류문제클릭후  try / catch 자동완성

 

package 스레드;

public class Sample04 {

	public static void main(String[] args) {

		Thread t1 = new Thread(new Runnable() {

			public void run() {
				for (int i = 0; i < 10; i++) {
					System.out.println("t1 : " + i);
					
					//1초마다 나오게하기 지연
					try {
						Thread.sleep(1000); //1000분의 1초 (1000입력시, 1초)
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		});
		
		t1.start();

	}

}

1초에 한 번씩 출력이 됨

 

 

toolkit.beep();

귀여운 소리가 남


.interrupt(); 

Thread가 대기 상태일때 강제로 예외를 발생시켜 종료

 

예제

 

package 복습용패키지;

public class 복습1 {
	
public static void main(String[] args) {
		
		Thread t1 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					int i = 1;
					while(true) {
						System.out.println("t1 : " + i);
						Thread.sleep(1000);
						i++;
					}
				} catch(InterruptedException e) {
					
				} //finally <-- 무조건 실행시키고 싶은게 있을 때
				
				System.out.println("스레드 종료");
				
			}
		}); /** 스레드 종료 시점 */
		
		t1.start();
		
		try {
			Thread.sleep(10000);
		} catch (Exception e) {
			
		}
		
		t1.interrupt(); //.interrupt 강제로 예외 발생 시켜주는 메서드
						//강제로 예외 발생 시켜서 종료 시켜준다.
						//정지 중인 상태에 대한 스레드만 강제로 예외 발생해준다.
						//sleep이랑 같이 사용

	}

}

.join(); 

우선식의 계산이 끝날 때까지 기다림

 

package 스레드;

public class Sum extends Thread{
	
	int sum = 0;

	public void run() {
		for(int i = 1; i<=100; i++) {
			sum += i;
			//1~100까지의 합
		}
	}
}

 

package 스레드;

public class Sample06 {

	  public static void main(String[] args) {

	      Sum t1 = new Sum();
	      Sum t2 = new Sum();
	   
	      t1.start();
	      t2.start();
	      
	      try {
	    	  t1.join(); //.join(); 
	    	  t2.join(); //.join(); //jonin : 위 t1의 계산이 끝날때까지 기다림
	      }catch(Exception e) {
	      
	   }
	      System.out.println(t1.sum+t2.sum);

	}
}

 


Thread.yield();

양보해서 다른 Thread를 먼저 실행 시킨다

 

예제

 

package 스레드;

public class Yt extends Thread{
	
	boolean isBreak = false;
	boolean isContinue = true;
	
	public void run() {
		while(!isBreak) {
			if(isContinue) {
				try {
					Thread.sleep(1000); //1초지연,1초마다 프린트문 출력
				} catch (InterruptedException e) {

				}				//스레드임시이름이 나옴
				System.out.println(getName() + "실행중");
			}else {
				Thread.yield(); //처리중인 작업을 양보함
			}
		}
		System.out.println(getName() + "종료");
	}

}
package 스레드;

public class Sample07 {

	public static void main(String[] args) {

		Yt t1 = new Yt();
		Yt t2 = new Yt();

		t1.start(); //스레드 실행
		t2.start(); //스레드 실행

		try {
			Thread.sleep(5000);
		} catch (Exception e) {

		}

		t1.isContinue = false; 
		//5초뒤 t1을 false, if문은 else로 넘어감

		try {
			Thread.sleep(5000);
		} catch (Exception e) {

		}

		t1.isContinue = true;
		//5초뒤 t1을 true if문에 t1 실행

		try {
			Thread.sleep(2000);
		} catch (Exception e) {

		}

		t1.isBreak = true;
		t2.isBreak = true;

	}

}

 

Thread-1 은 t1 / Thread-0 은 t2

 


동기화

synchronized : 동기화, 한 번에 한 개 스레드만 공유자원(SmartPhoneGame)에 접근하도록 잠금
다른 스레드는 진행 중인 작업을 간섭 못함.

공유자원을 썼을 때만 사용할 수 있다.

 

public synchronized void 메서드이름() {
		(한개 스레드만 실행)
	}

========================================

public void 메서드이름() {
	(여러스레드실행가능)
	synchronized (공유객체) {
    		(한개 스레드만 실행)
    	}
        (여러 스레드 실행 가능)
    }

 

예제) 

 

스레드 문(공유자원문), player1/player2가 동시에 공유사용

package 스레드;

public class SmartPhoneGame {

	   private int level;

	   public int getLevel() {
	      return level;
	   }
	   //synchronized : 동기화, 한번에 한개 스레드만 공유자원(SmartPhoneGame)에 접금하도록 잠금
	   //다른 스레드는 진행중인 작업을 간섭 못함.
	   public synchronized void increaseLevel() {

	      while (true) {
	         this.level++;
	         try {
	            Thread.sleep(1000);
	         } catch (Exception e) {
	         }
	         System.out.println(Thread.currentThread().getName() + "lv: " + this.level);

	         if (this.level % 10 == 0) {
	            break;
	            //Player1,2 모두 같은 while문을 사용하기때문에
	            //p1과p2가 동시에 레벨이 오르기때문에 레벨이 2씩 오름
	            //각각의 객채문을 사용하면됨

	         }
	      }
	   }
	}

 

package 스레드;

public class Player1 extends Thread{
	
	private SmartPhoneGame game;

	public void setGame(SmartPhoneGame game) {
		this.setName("Player1"); 
        //setName은 상속받은 Thread를 가리켜서 Thread에 이름을 "Player1로 설정해준다.
		this.game = game;
	}
	
	public void run() {
		game.increaseLevel();
	}

}

 

 

package 스레드;

public class Player2 extends Thread{

	private SmartPhoneGame game;

	public void setGame(SmartPhoneGame game) {
		this.setName("Player2");
		this.game = game;
	}
	
	public void run() {
		game.increaseLevel();
	}

}

실행 메인 문

package 스레드;

public class Main {

	public static void main(String[] args) {
		
		SmartPhoneGame game = new SmartPhoneGame();
		
		Player1 p1 = new Player1(); //Player1 객채생성
		p1.setGame(game);
		
		Player2 p2 = new Player2(); //Player1 객채생성
		p2.setGame(game);
		
		p1.start();
		p2.start();
		//synchronized 사용으로 p1끝나면 p2가 작동
		//동시에 p1,p2가 출력되는 것을 방지

	}

}

 

 

 

728x90
Comments