본문 바로가기

programming/Gukbi

국비 교육 29일차 - Thread

728x90
반응형

피곤...

 

겨우 이제 조금씩 다 알겠네 싶었는데 Thread라는 놈이 나와서 날 괴롭히고 있다...

살려주세요..

 

프로세스 : 실행 중인 프로그램, 자원(resources)과 쓰레드로 구성

쓰레드: 프로세스 내에서 실제 작업을 수행한다. - 모든 프로세스는 최소한 하나의 쓰레드를 가지고 있다. 

 

프로세스 : 쓰레드 = 공장 : 일꾼

 

- 싱글 쓰레드 프로세스

= 자원+쓰레드

 

- 멀티 쓰레드 프로세스

= 자원+쓰레드+쓰레드+쓰레드 // 대부분의 프로그램이 멀티쓰레드로 작성되어 있다. 

 

*멀티쓰레드 단점

- 동기화되지 않게 주의해야함

-교착상태(dead-lock)가 발생하지 않도록 주의해야한다

-각 쓰레드가 효율적으로 고르게 실행될 수 있게 해야한다. 

=> 장점이 많지만 프로그래밍할때 주의해야할 사항이 많아진다

 

1) Thread 상속

class MyThread extends Thread {}

-> 자바는 단일 상속을 허용하기 때문에

 

2) Runnable 인터페이스를 구현 

class MyThread2 implements Runnable {

public void run(){}

}

-> 아래 Runnable 인터페이스를 구현하는게 훨씬 좋음

run()이라는 메소드만 따로 구현해주면 되기 때문에

 

package com.sist.thread;
class MyThread extends Thread {
	
}
class MyThread2 implements Runnable {
public void run(){}
}

public class MainClass6 {

	public static void main(String[] args) {
		MyThread t1=new MyThread();
		
		//Runnable r = new MyThread2();
		//Thread t2=new Thread(r);
		Thread t2=new Thread(new MyThread());
	}

}

인터페이스, 클래스는 각각의 방법으로 생성해줄 수 있다. 

 

쓰레드를 생성하고, start() 메소드를 써야 쓰레드를 실행시킬 수 있다. 

package com.sist.thread;
/*
 *  Thread : 하나의 프로그램안에서 여러개의 기능을 동시에 수행
 *  		 ========== (프로세스)
 *  		 쓰레드는 메소드 호출 : 게임, 채팅, 웹 - 통신하는 프로그램이 각각 다르게 작동함 (서버=>통신기능)
 *  
 *  웹서버는 이미 만들어져 있음, 접속할때마다 thread를 만들어줌 -> 그렇기 때문에 깊게 배우지 않는 것 
 *  (서버 : 톰캣, 아파치)
 *  1. 쓰레드 구현과 실행 
 *  	1) Thread를 상속 (Thread는 클래스) => 멀티스레드 
 *  		public class MyThread extends Thread
 *  		{
 *  		}
 *  	2) Runnable 구현 (Runnable 인터페이스) => 싱글스레드(윈도우)
 *  		====== 이미 상속이 있는 경우에 주로 사용
 *  		public class MyThread implements Runnable
 *  		{
 *  			public void run()
 *  			{
 *  			 쓰레드 동작을 코딩
 *  			}
 *  		}
 *  2. 쓰레드 생령주기 					=====> Blocked (일시정지)
 *  	new ====> Runnable ===> Running 
 *  								=====> Dead (메모리 해제)
 *  	1) new
 *  		Thread t=new Thread();
 *  	  => JVM
 *  		 = 이름 부여됨 (Thread-0...)
 *  		   이름 가지고 오기 : getName()
 *  		   이름 변경 : setName()
 *  		 = 우선순위 부여 (1~10)
 *  		   1: MIN_PRIORITY
 *            10: MAX_PRIORITY
 *             5: NORM_PRIORITY (사용자 정의)
 *            == 기준 (작업종료)
 *            = 쓰레드는 한가지 일만 수행
 *            	예) 서버 / 클라이언트 (서버로부터 응답값을 받아서 출력)
 *            	클라이언트
 *            		1) 서버에 요청 : 채팅문자열을 접속자 전체 전송
 *            					  응답메세지 출력 (쓰레드)
 *            		2) 게임 : 비행기
 *            				 비행기 총알
 *            				 아바타 총알
 *            			     아바타
 *       2) Runnable (대기상태) => 자원 (CPU => 메모리공간) 공유		
 *       	start()
 *       3) Running (쓰레드 실행) => 쓰레드가 어떻게 동작을 할지 코딩
 *       	run() //Every Thread must have run method	
 *       4) 실행하는 과정 : 일시정지
 *       	sleep()
 *       5) 종료: 쓰레드 해제
 *       	interrupt()
 *  3. 쓰레드는 데이터가 없다 => 프로세스의 데이터 공유해서 사용(내부클래스)
 *  class Game
 *  {
 *  		Game과 관련된 데이터
 *  
 *  		class ThreadEx extends Thread
 *  		{
 *  			
 *  		}
 *  }
 *  
 */
class MyThread extends Thread
{
	// 동작 
	public void run()
	{
		for(int i=1; i<=10; i++)
		{
			System.out.println(Thread.currentThread()+":"+i);
			try
			{
				Thread.sleep(1000); // 1/1000초 => 일시정지
			}catch(Exception ex) {}
		}
	}
}
/*
 * 	모든 프로세스는 main()부터 시작한다
 * 				======
 * 				Thread ==> 모든 프로세스는 한개 이상의 쓰레드를 가지고 있다 
 * 
 * 
 */
public class MainClass {

	public static void main(String[] args) {
		// Thread 생성
		System.out.println(Thread.currentThread()); // main도 쓰레드 
		MyThread t1=new MyThread();
		MyThread t2=new MyThread();
		MyThread t3=new MyThread();
		MyThread t4=new MyThread();
		MyThread t5=new MyThread();
		
		t1.setName("이제노");
		t2.setName("황런쥔");
		t3.setName("박지성");
		t4.setName("종천러");
		t5.setName("이마크");
		
		// 우선순위 1(MIN) ~ 5(NORM)default  10(MAX)
		/*		   =====    =====    		 ====
		 * 
		 */
		t1.setPriority(Thread.MIN_PRIORITY);
		t2.setPriority(10);
		t3.setPriority(1);
		t4.setPriority(1);
		t5.setPriority(1);
		
		
		// 대기상태 => start() 
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start(); // 시분할 (한번씩 수행)
		
		
		// 실행상태 => run()
		// start)( => run() 자동호출
	}

}

우선 쓰레드 자체는 비동기화 방식으로 실행된다. 

메소드의 경우 하나의 메소드가 끝나면 그 다음에 다른 메소드가 호출되는 동기화 방식이었다면, 쓰레드는 순서가 정해져 있지 않고 랜덤으로 실행된다. 

 

JVM이 랜덤으로 실행시키기 때문에 사람이 그 순서를 제어할 수 없다. 

 

스레드 클래스를 먼저 만들어주고 그 다음에 생성자를 사용해서 객체를 생성한다. 

setName();

setPriority(); 메소드를 통해 필요한 값을 지정해준다. 

 

그 다음 start(); 메소드를 사용하면 자동으로 run(); 메소드가 호출되면서 실행된다. 

그 실행된 결과값은 캡쳐에서 확인할 수 있다. 

 

옆을 보면 알 수 있듯이 for문에서 1을 먼저 한바퀴 돌고 그 다음 2가 실행된다. 

t1, t2, t3, t4, t5 쓰레드는 숫자 순서대로 써줬지만 실행은 랜덤으로 이루어지는 것을 확인할 수 있다. 

 

 

싱글 Thread를 사용하면 이처럼 각각의 패널들의 색을 채워주는 것을 확인할 수 있다. 

하지만 위부터 순서대로 채워지고 있기 때문에 별다른 큰 차이점을 느끼지 못할 수도 있다. 

 

package com.sist.thread;
/* 
 * 실시간 = 쓰레드
 * 프로그램의 사용처를 알아가야함 -> 그래야 나가서 프로그램 분석이 가능해짐
 * 소스 분석을 할 줄 알아야함, 그래야 유지 보수가 가능해짐
 * 
 */
import javax.swing.*; // Component(Button...), Container(윈도우)
import java.awt.*;
import java.awt.event.*; // Event 사용자가 눌렀을때 부터 동작하는 것 - 사건이 발생한다
public class MainClass3 extends JFrame implements ActionListener{ // ActionListener-버튼을 누르면 처리해줌
	JProgressBar[] bar=new JProgressBar[5];
	
	JButton b1, b2;
	// 초기화 (객체 메모리 할당 => 배치 => 윈도우 크기 => 윈도우를 보여준다)
	
	
	BarThread[] bt=new BarThread[5];
	static int rank;
	
	public MainClass3()
	{
		b1=new JButton("start");
		b2=new JButton("ends");
		
		
		JPanel p=new JPanel();
		p.setLayout(new GridLayout(5,1,5,5));// 5행 1열 5,5는 간격에 해당함
		Color[] color= {Color.yellow, Color.pink, Color.cyan, Color.orange, Color.green};
		for(int i=0; i<5; i++)
		{
			bar[i]=new JProgressBar(); // 객체배열은 항상 메모리 할당 해줘야함
			bar[i].setMinimum(0);
			bar[i].setMaximum(100);
			bar[i].setStringPainted(true);
			bar[i].setBackground(Color.white);
			bar[i].setForeground(color[i]);
			p.add(bar[i]);
		}
		
		JPanel p2=new JPanel();
		p2.add(b1); p2.add(b2);
		
		// 윈도우 추가
		add("Center", p);
		add("South", p2);
		
		// 크기
		setSize(640, 350);
		setVisible(true);
		
		// 등록
		b1.addActionListener(this);
		b2.addActionListener(this);
	}
	public static void main(String[] args) {
		new MainClass3();
	}
	// 프로그래스바가 동작 => 쓰레드 (5개가 동작을 다르게 만든다)
	class BarThread extends Thread
	{
		//프로그래스바 한개만 작동하게 만든다
		int index;
		public BarThread(int index)
		{
			this.index=index;
		}
		// 동작을 구현
		public void run()
		{
			for(int i=0; i<=100; i++)
			{
				bar[index].setValue(i);
				int a=(int)(Math.random()*300); // 일시정지
				try
				{
					Thread.sleep(a); // 랜덤으로 속도를 만든 것
				}catch(Exception ex) {}
				
				if(i==100)
				{
					rank++;
					interrupt(); // 쓰레드 종료
				}
			}
			System.out.println(rank+"등:"+(index+1)+"번째");
		}
	}
	// 쓰레가 프로그래스바를 공유 => 멤버 클래스 
	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource()==b1)
		{
			for(int i=0; i<5; i++)
			{
				bt[i]=new BarThread(i);
				bt[i].start();
			}
		}
		if(e.getSource()==b2)
		{
			System.exit(0);
		}
	}
	
	// 클래스와 클래스 => 데이터 공유 (내부 클래스, static)
	/*
	 * 내부 클래스
	 * 	= 멤버 클래스 : 데이터 공유 (메모리 할당이 없는 상태에서 메모리를 공유) => 윈도우, 쓰레드 , 네트워크 
	 * 				 네트워크 : 서버(한 컴퓨터에서 두번을 실행하면 오류 발생)
	 * 		public class A
	 * 		{
	 * 			윈도우
	 * 			main()
	 * 			{
	 * 				A a=new A(); => 윈도우를 보여라
	 * 			}
	 * 			class MyThread extends Thread // 기존에 있는것을 제어해야하기 때문에, new로 새로운 창을 띄우지 x
	 * 			{
	 * 		
	 * 			}
	 * 		}
	 * 		
	 * 	=
	 * 	=
	 * 	=
	 */
}

이해가 안간다...

 

하아 ㅋㅋ^^ ㅠㅠ 흑흑 @@

 

728x90
반응형