ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 9. 스레드(Thread) 정의가 뭘까?
    Programming/JAVA 2010. 5. 3. 21:08

    1 스레드 기본
    1.1 프로세스와 스레드

    프로세스(Process)

    하나의 프로그램(Program)은 하나의 프로세스(Process)에 해 당한다.

    멀티 태스킹(Multi-Tasking)

    프로세스(Process)의 경우 운영체제에서 자동으로 관리해준다.

    운영체제 차원의 프로세스(Process) 관리를 멀티 태스킹 (Multitasking)이라고 한다.

    프로세스(Process)와 스레드(Thread)

    하나의 프로세스(Process) 내에는 여러 개의 스레드(Thread) 가 존재할 수 있다.
    1.2 스레드(Thread)란

    스레드(Thread)란?

    하나의 프로그램 내에서 실행되는 메서드

    같은 순간에 두 개의 메서드가 동시에 실행되면 두 개의 스레드가 동작하는 것이다.
    1.2 스레드(Thread)란

    시퀀셜(Sequential)하게 동작한다.

    한순간에하나의메서드가동작하는것을'시퀀셜하 게 동작한다'라고 한다.

    스레드의 기본

    한 순간에 두 개의 메서드가 동시에 실행되었을 때, 실행된 메서드들을 스레드(Thread)라고 한다.

    스레드란?

    프로그램에서 독립적으로 실행되는 메서드

    스레드에서의 중요 사항

    스레드를 어떻게 만드는가?

    왜 스레드를 메서드라고 하는가?
    1.3 스레드 만들기

    스레드를 만드는 방법은 두가지가 있다.

    Thread 클래스를 상속하여 run 메서드를 재정의

    Runnable 인터페이스를 구현하여 run 메서드를 재정의
    1.3 스레드 만들기

    Top 클래스 내에 run() 메서드 작성

    Thread클래스 상속
    public class Top extends Thread{
    public void run(){
    //스레드의세부내용
    }
    }

    run메서드는 start메서드를 호출해서 실행한다.
    public class TopMain {
    public static void main(String[] args){
    Top t = new Top();
    t.start();
    }
    }
    1.3 스레드 만들기

    Top 클래스내에run() 메서드작성

    예제
    class Top extends Thread{
    public void run(){
    System.out.println("RUN");
    }
    }
    public class TopThread{
    public static void main(String[] args){
    System.out.println("Start");
    Top t = new Top();
    t.start();
    System.out.println("End");
    }
    }
    1.3 스레드 만들기

    Top 클래스 내에 run() 메서드 작성(2)

    Runnable 인터페이스 구현
    public class Top implements Runnable{
    public void run(){
    //스레드의세부내용
    }
    }

    run메서드는 start메서드를 호출해서 실행한다.
    public class TopMain {
    public static void main(String[] args){
    Top t = new Top();
    Thread th = new Thread(t);
    th.start();
    }
    }
    1.3 스레드 만들기

    Top 클래스내에run() 메서드작성

    예제
    class Top implements Runnable{
    public void run(){
    System.out.println("RUN");
    }
    }
    public class TopRunnable{
    public static void main(String[] args){
    System.out.println("Start");
    Top t = new Top();
    Thread th = new Thread(t);
    th.start();
    System.out.println("End");
    }
    }
    1.4 두 개의 스레드 만들기

    2개의 스레드를 동시에 실행

    Runnable을 구현하는 객체 만들기

    Top t = new Top();

    Runnable을 장착한 후 진짜 스레드 만들기

    Thread thd1 = new Thread(t);

    Thread thd2 = new Thread(t);

    스레드 동작 시키기

    thd1.start();

    thd2.start();
    1.4 두 개의 스레드 만들기

    2개의 스레드를 동시에 실행

    예제
    class Top implements Runnable{
    public void run(){
    System.out.println("RUN");
    }
    }
    public class TopDoubleThread{
    public static void main(String[] args){
    System.out.println("Start");
    Top t = new Top();
    Thread th1 = new Thread(t);
    Thread th2 = new Thread(t);
    th1.start();
    th2.start();
    System.out.println("End");
    }
    }
    1.4 두 개의 스레드 만들기
    main()
    두 개의 스레드 실행 순서
    public void run(){
    for(int i=0; i<50; i++)
    System.out.print(i+"\t");
    }
    Runnable run()
    public void run(){
    for(int i=0; i<50; i++)
    System.out.print(i+"\t");
    }
    Runnable run()
    동시에작업진행
    System.out.println("프로그램 시작");
    Top t = new Top();
    Thread thd1 = new Thread(t);
    Thread thd2 = new Thread(t);
    thd1.start();
    thd2.start();
    System.out.println("프로그램 종료");
    Thread thd1
    Thread thd2
    1.5 Runnable을 사용하는 이유

    다른 클래스를 상속했기 때문에 Thread를 상속할 수 없는 경우

    즉 이미 다른 클래스를 상속해야 한다면 Thread를 상속 할 수 없기 때문에 Runnable 인터페이스를 구현해야 한 다.
    class RunFrame extends Frame{
    //...작업
    }

    Frame은 상속을 하고 Runnable은 구현을 한 상태
    class RunFrame extends Frame implements Runnable{
    public void run(){
    //...스레드내의작업
    }
    }
    1.5 Runnable을 사용하는 이유
    import java.awt.*;
    class RunnableFrameextends Frame implements Runnable{
    public void run() {
    inti = 0;
    System.out.println("스레드시작!");
    setSize(300, 100);
    setVisible(true);
    while(i<20) {
    System.out.print(i+ "\t");
    this.setTitle("스레드동작중"+ i++);
    try{
    Thread.sleep(500);
    }catch(InterruptedExceptione){System.out.println(e);}
    }
    System.out.println("스레드종료!");
    dispose();
    }
    }
    public class RunnableFrameMain{
    public static void main(Stringargs[]){
    RunnableFramer = new RunnableFrame();
    Thread t = new Thread(r);
    t.start();
    //new Thread(newRunnableFrame()).start();
    }
    }
    2 스레드의 상태와 제어
    2.1 스레드의 상태

    NotRunnable상태를 만드는 방법

    sleep()은 일정 시간 동안만 NotRunnable상태로 만든다.

    wait()와 notify()는 수동으로 NotRunnable상태로 들어 가고 나오는 것을 제어할 수 있다.
    sleep(시간) -> 시간지나면
    wait() -> notify()
    sleep(시간), wait()
    Thread
    Thread
    스레드(Thread)의 상태 구조도
    Thread
    Thread
    Dead
    NotRunnable
    Start
    Runnable
    Thread
    Thread
    Thread
    Thread
    Thread
    Thread
    Thread
    Thread
    Thread
    Thread
    Run
    Thread
    스레드의 우선권에 따라서
    Run을 차지할 권한이 달라진 다.
    run()의 종료는 스레드의 종료
    start()를 호출했을 때
    자동진입
    wait()
    wait()하면 NotRunnable 상태가 되지만 notify() 해주어야만 Runnable 상태로 되돌아 올 수 있다.
    sleep(시간)
    일정시간 동안만 NotRunanble 상태가 된다.
    시간이 지나면 자동으로 Runnable 상태가 된다.
    2.2 스레드의 우선권

    Thread 클래스의 스태틱 우선권 상수

    public static final int MIN_PRIORITY = 1;

    public static final int NORM_PRIORITY = 5;

    public static final int MAX_PRIORITY = 10;

    스레드를 NotRunnable 상태로 만드는 방법

    sleep()을 이용해서 일정시간 동안 대기시키는 방법(자동)

    wait()/notify()로 대기/복귀를 제어하는 방법(수동)

    sleep()의 사용
    try{
    Thread.sleep(1000); //시간의단위는1/1000초
    }catch(InterruptedException e){
    e.printStackTrace();
    }
    2.2 스레드의 우선권
    class PriorityThread extends Thread {
    public void run() {
    System.out.println(this.getName() + “[우선권:" + this.getPriority() + "] 시작\t");
    try{
    this.sleep(1);
    }catch(Exception e){System.out.println(e);}
    System.out.println(this.getName() + “[우선권:" + this.getPriority() + "] 종료 \t");
    }
    }
    public class PriorityThreadMain {
    public static void main(String[] args) {
    System.out.println("Main메서드시작");
    for(int i=Thread.MIN_PRIORITY; i<=Thread.MAX_PRIORITY; i++){
    PriorityThread s = new PriorityThread();
    s.setPriority(i);
    s.start();
    }
    System.out.println("Main메서드종료");
    }
    }
    2.3 NotRunnable 상태 만들기 I

    sleep()을 이용한 작업의 일시 중단 - main()에서의 Thread.sleep()
    public class NotRunnableMain{
    public static void main(String[] args){
    long current = System.currentTimeMillis();
    System.out.println("프로그램시작");
    try{
    Thread.sleep(5000);
    }catch(InterruptedException e){e.printStackTrace();}
    System.out.println("프로그램종료");
    System.out.println("시간: " + (System.currentTimeMillis()-current));
    }
    }
    2.4 NotRunnable 상태 만들기 II
    import java.util.*;
    class NotRunnableThread extends Thread {
    public void run() {
    int i = 0;
    while(i < 10) {
    System.out.println(i + "회:" + System.currentTimeMillis() + "\t");
    i = i + 1;
    try{
    this.sleep(1000);
    }catch(Exception e){System.out.println(e);}
    }
    }
    }
    public class NotRunnableThreadMain {
    public static void main(String args[] ) {
    NotRunnableThread s = new NotRunnableThread();
    s.start();
    }
    }
    NotRunnable 상태 만들기
    3 동기화
    3.1 멀티 스레드와 문제점

    스레드의 문제점

    스레드들이 여러 개 동시에 작업을 진행하기 때문에 공유자원의 문제가 발생한다.

    이를 동기화 문제라고 한다.

    동기화 문제가 발생하는 상황

    A, B, C라는 세 사람이 화장실을 사용하려고 한다.

    화장실이 하나밖에 없다.

    세사람이 동시에 화장실을 사용하려 한다.
    3.1 멀티 스레드와 문제점

    화장실의 동기화 기법(Lock)

    A가 사용하고 있을 때 문을 잠그고(Lock), 그리고 다 사용하고 나면 다른 사람이 사용하면서 문을 잠그는 기법을 이용한다.

    동기화(Synchronization)의 정의

    줄서기(번갈아 가면서 순서대로 공유자원 사용하기)

    동기화(Synchronization)의 기법

    synchronized 블록

    자원을 사용할 때 자원에 락(Lock)을 거는 방식

    wait()와 notify()
    3.2 동기화가 보장되지 않는 예제

    예제
    class Data{
    public int i = 0;
    }
    class Tom extends Thread{
    public void run(){
    for (int i=0;i<100000; i++){//Tom이 100000번 증가시킨다.
    NotSyncDataMain.data.i++;
    }
    System.out.println("Tom :" + NotSyncDataMain.data.i);
    }
    }
    class Jane extends Thread{
    public void run(){
    for (int i=0;i<100000; i++){//Jane이 100000번 증가시킨다.
    NotSyncDataMain.data.i++;
    }
    System.out.println("Jane:" + NotSyncDataMain.data.i);
    }
    }
    3.2 동기화가 보장되지 않는 예제

    예제
    class NotSyncDataMain{
    public static Data data = new Data();
    public static void main(String[] args){
    System.out.println("main 시작");
    Tom t = new Tom();
    Jane j = new Jane();
    t.start();
    j.start();//Tom과Jane이동시에Data의i를증가시킨다.
    System.out.println("main 종료");
    }
    }

    결과

    예상 결과는 200000, 하지만 동기화가 보장되지 않기 때문에 어느 순간 에는 동시에 수를 증가시킨다.
    3.3 동기화 보장 예제

    예제
    class Data{
    public int i = 0;
    }
    class Tom extends Thread{
    public void run(){
    for (int i=0;i<100000; i++){
    synchronized(SyncDataMain.data){
    SyncDataMain.data.i++;
    }
    }
    System.out.println("Tom :" + SyncDataMain.data.i);
    }
    }
    class Jane extends Thread{
    public void run(){
    for (int i=0;i<100000; i++){
    synchronized(SyncDataMain.data){
    SyncDataMain.data.i++;
    }
    }
    System.out.println("Jane:" + SyncDataMain.data.i);
    }
    }
    3.3 동기화 보장 예제

    예제
    class SyncDataMain{
    public static Data data = new Data();
    public static void main(String[] args){
    System.out.println("동기화보장예제시작");
    Tom t = new Tom();
    Jane j = new Jane();
    t.start();
    j.start();
    System.out.println("동기화보장예제종료");
    }
    }

    결과

    Tom과 Jane은 동기화가 보장된 상태에서 수를 증가시킨다.

    실행결과는 실행할 때 마다 다르다.
Designed by Tistory.