본문 바로가기

프로그래밍 언어/Java

Week10) Java Programming Lab : Multithreading

Java-Lecture10.pdf
0.90MB

1. Introduction


1.1 멀티쓰레딩이란?

  • 멀티쓰레딩 = 멀티프로세싱
  • 멀티 프로세싱 운영체제는 동시에 여러개의 프로세스를 실행시킨다
    • 각 프로세스는 자신만의 주소 및 메모리 공간을 갖는다.
    • 운영체제 스케줄러는 어떤 프로세스를 실행시킬지 결정하는데 한번에 오직 하나의 프로세스만 실행가능하다.
    • 그런데 시스템이 동시에 여러 프로세스가 실행되는 것'처럼' 보이게 하는 것 
  • 멀티쓰레드 애플리케이션은 동일한 메모리 공간 내에서 여러 개를 실행 포인트가 있다. 
    • 각 테스크들이 분리된 쓰레드로 동작함
    • 하나의 쓰레드가 오래걸리는 것이 전체 애플리케이션이 그 쓰레드 하나를 끝낼때까지 기다리게 하지 않음 
  • 싱글쓰레드 애플리케이션에서는 하나의 실행 쓰레드가 모든 것을 해야 한다.
    • 메인 메소드 있는 클래스에서 모든 것을 run!
    • 모든 것을 순차적으로 진행하는데 특정 테스크 하나가 느리면 시스템 전체가 느리다고 느껴짐

2. Defining and Starting a Thread in Java


  • 쓰레드의 인스턴스를 생성하는 애플리케이션은 반드시 해당 쓰레드가 실행되는 코드를 제공해야 한다 
    • 방식 1) 쓰레드 클래스 subclassing -> 서브 클래스에서 새로운 객체 만들기 (extends Thread) 
    • 방식 2) Runnable interface 구현 (implements Runnable) 
    • 위의 모든 방식은 run() 메소드를 구현해야 함 
     

 

2.1 Examples

import java.util.Arrays;

public class Example1 {

	public static void main(String[] args) {
    
    	
		Thread mainThread = Thread.currentThread();
		System.out.println(mainThread);
		
 		runableTask1 object1 = new runableTask1();
 		runableTask2 object2 = new runableTask2();
        
        // 쓰레드 이름 설정 가능 new Thread(.., .., 쓰레드 이름); 
        // 생성한 객체를 두번째 인자로 전달하는 방식
 		Thread thread1 = new Thread(mainThread.getThreadGroup(),object1,"Thread1");
        // 객체 생성자체를 파라미터에서 
 		Thread thread2 = new Thread(mainThread.getThreadGroup(),new runableTask2(),"Thread2");
 		// 객체 생성 함수도 여기서 작성 가능 
        Thread thread3 = new Thread(mainThread.getThreadGroup(),new Runnable() {
			@Override
			public void run() {
				System.out.println("Task3");
			}
		} ,"Thread3");
        
        // 쓰레드 객체 만들고 쓰레드 실행시키는 코드 반드시 필요 
 		thread1.start();
 		thread2.start();
 		thread3.start();
 		 
		mainThread.getThreadGroup().list();
		 
	}
}

class runableTask1 implements Runnable{

	@Override
	public void run() {
		// the task your thread will do
		int [] array = new int [100];
		for (int i = 0 ; i<100;i++) {
			array[i]=i;
		}
		
		try {
        	// 쓰레드 잠시 block 상태로 만드는 메소드 sleep()
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println(Arrays.toString(array));
	}
	
}


class runableTask2 implements Runnable{

	@Override
	public void run() {
		// the task your thread will do
		 
		System.out.println("Task2");
	}
	
}
public class example2 {
	public static void main(String[] args) {
		task1 object = new task1();
		object.start();
	}
}

class task1 extends Thread {
	@Override
	public void run() {
		System.out.print("Task1");
	}
}

 

  • runnable 인터페이스를 구현해서 쓰레드 만드는 방식이 더 흔하게 사용됨 (첫번째 예시) 

3. Thread States


  • 쓰레드 상태 : created, running, blocked, dead
  • sleep() 메소드로 쓰레드 block 가능, 잠시 해당 쓰레드 실행 멈춤 
  • example
public class Racer implements Runnable {

	public  String winner;
    // 생성자
	public void race(){
			
	}

	private boolean isRaceWon(int totalDistanceCovered){
		boolean isRaceWon =  false;
		if((winner==null )&&(totalDistanceCovered==100)){
				String winnerName = Thread.currentThread().getName();
				winner = winnerName; //setting the winner name
				System.out.println("Winner is :"+winner);
				isRaceWon = true;
			}else if(winner==null){
			isRaceWon = false;
			}else if(winner!=null){
				isRaceWon = true;
			}
		return isRaceWon;
		}

	@Override
	public void run() {
		for(int distance=1;distance<=100;distance++){
			boolean isRaceWon = this.isRaceWon(distance);
			// 누군가 win하면 isRaceWon 값이 true 로 바뀌어 반목분 break
			if(isRaceWon){
				break;
			}
			System.out.println("Distance Covered by "+
		Thread.currentThread().getName()+ " is:"+distance +"meters");
		//Check if race is complete if some one has already won
		
	}

	}

}
public class RaceDemo {
	public static void main(String[] args) {
		Racer racer = new Racer();
		Thread tortoiseThread = new Thread(racer, "Tortoise");
        // 아래 코드로 Tortoise 쓰레드에 우선순위를 최상으로 하면 항상 이 스레드가 win! - 치팅 코드!
		tortoiseThread.setPriority(Thread.MAX_PRIORITY); // MIN으로 하면 getPriority = 1 MAX = 10
        // 쓰레드 이름 바꾸기 
        tortiseThread.setName("Seungyoon");
		System.out.println(tortoiseThread.getPriority());  // normal = 5 (우선순위 set 안하면 5 가 디폴트)
		Thread hareThread = new Thread(racer, "Hare");
		//Race to start. tell threads to start
		tortoiseThread.start();
		hareThread.start();

	}
}

4. Thread property access methods


5. State transition methods for Thread


6. Thread synchronization


  • 멀티쓰레드 -> 동일 메모리에 대한 동시 접근 발생 -> Memory consistency error 발생 가능 
  • 여러 개의 쓰레드가 하나의 변수에 동시에 접근하면 해당 변수가 저장되어 있는 메모리는 어떤 값을 최종 값으로 저장해야 하는지 혼란스럽다. 
  • 이를 해결하기 위해 동기화 필요 -> Synchronized solution 
  • example
    • 같은 변수에 접근하는 모든 쓰레드들은 동시에 실행될 수 없게 하는 것 synchronized 키워드 !! 
    • 한 쓰레드의 작업 마친 후에 다음 쓰레드가 랜덤으로 실행 됨 

class Counter{
  int count;
  // incre()에 대해 sychronized 키워드를 붙이면 t1 t2를 동시에 실행시켜도 결과가 일관되게 나옴
  public synchronized void incr(){count++;}
}
public class Main {
  public static void main(String[] args)throws InterruptedException {

    Counter c = new Counter();
    
    Thread t1 = new Thread(new Runnable(){
      public void run(){
        for(int i=0; i<1000; i++)
          c.incr();
      }
    });

    Thread t2 = new Thread(new Runnable(){
      public void run(){
        for(int i=0; i<1000; i++)
          c.incr();
      }
    });

	// 이렇게 두개를 동시에 실행시키면 
    // c에 대한 값에 두 쓰레드가 동시에 접근해서 매번 다른 값이 결과로 나오게 됨 
    t1.start();
    t2.start();

    t1.join();
    t2.join();
    
    System.out.println("Count = " + c.count);
  }
}

 

  • Thread - wait() 메소드
    • block thread
    • 쓰레드 실행을 기다리게 하는 것
  • Thread - notify() 메소드 
    • block 상태로 wait 기다리고 있는 쓰레드 랜덤으로 선택해서 깨우는 것 

 

7. Thread Groups


public class example3 {
	public static void main(String[] args) {
		ThreadGroup threadGroup = new ThreadGroup("Network Threads");

		Thread t1 = new Thread(threadGroup, new Runnable() {

			@Override
			public void run() {
				System.out.println("network task1");

			}
		});

		Thread t2 = new Thread(threadGroup, new Runnable() {

			@Override
			public void run() {
				System.out.println("network task2");

			}
		});
		t1.start();
		t2.start();
      
		//stop all threads of the network
		threadGroup.interrupt();
		threadGroup.list();
		
		
	}
}

 

  • Thread.currentThread()  : 현재 실행 중인 쓰레드 반환 

 

8. Threading in Swing


  • swingworker 메소드 예시 

 

 

 

References


  • 성균관대학교 소프트웨어학과 타메르 교수님 <자바 프로그래밍 실습> 

Lecture10-codes.zip
0.01MB