아무거나

스레드(Thread) 본문

Java & Kotlin/Java

스레드(Thread)

전봉근 2019. 8. 16. 23:52
반응형

[JAVA 스레드]

멀티 프로세스 : 컴퓨터가 여러 가지 일을 동시에 하고 있는 것을 뜻함.

스레드(멀티스레드) : 위에서 말한 하나의 프로세스에서 다시 여러 가지 일을 하는 것을 뜻 합니다. 예를 들어 파일을 전송하면서

채팅을 하고 있다. 동일한 채팅프로그램에서 파일전송과 채팅을 동시에 하고 있는 것 입니다.

 

 

채팅 프로그램 프로세스 -> 파일전송 스레드

-> 채팅 스레드

 

JAVA는 기본적으로 멀티스레드를 지원 하고 있습니다.

스레드는 두 가지 형태로 존재 합니다.

 

방식1) 객체 하나를 n개의 스레가 공유 하는 방식

스레드0 ->

스레드1 -> 객체0

스레드2 ->

 

방식2) 객체 하나당 하나의 스레드가 존재하는 방식이다.

스레드0 -> 객체0

스레드1 -> 객체1

스레드2 -> 객체2

 

 

# 멀티 스레드 문법

* run method를 반드시 구현 하여야 한다.

(어떤 일을할때의 로직이 run 메소드안에서 구현되어야 한다. 즉 Thread가 하는 일들이 모여있다.)

 

1. Runnable 인터페이스 구현을 통한 Thread

* Main Thread에서 내가 만든 Thread를 사용할 떄의 예시이다.

ex) [MainClass.java]

public class MainClass {
    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        Thread thread = new Thread(threadTest, "A");
        thread.start();


        System.out.println(Thread.currentThread().getName());
        System.out.println("MainClass");
    }
}

 

 

[ThreadTest.java]

public class ThreadTest implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()); // Thread 이름
        System.out.println("ThreadTest");

        for (int i=0; i<10; i++) {
            System.out.println("i =" + i);


            try {
            // Thread를 사용할땐 try ~ catch 안에 구현가능
            Thread.sleep(1000); // 컴퓨터 안에서 돌아가는 시간대가 다르므로 정확한 시간이 아니다(컴퓨터 성능별로 차이가 있음)
            } catch (Exception e) {

            }
        }
    }
}

 

 

[결과]

// main이 먼저 찍히는 이유는 run()에서 Thread가 도는것과 main이 하는것과는 별개다
// 그러므로 main은 thread가 돌던말던 자기 할일을 끝내기 때문에 main이 먼저 출력된 것이다.
main
MainClass
A
ThreadTest
i =0
i =1
i =2
i =3
i =4
i =5
i =6
i =7
i =8
i =9

 

 

 

2. Thread 클래스를 상속 통한 Thread

ex) [MainClass.java]

public class MainClass {
    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        threadTest.setName("B");
        threadTest.start();


        System.out.println(Thread.currentThread().getName());
    }
}

 

 

[ThreadTest.java]

public class ThreadTest extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
        for (int i=0; i<10; i++) {
            System.out.println(i);


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

 

 

[결과]

main
B
0
1
2
3
4
5
6
7
8
9

 

 

 

3. 객체 1개, 스레드n개가 돌아가는 방식

[MainClass.java]

public class MainClass {
    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();

        Thread thread0 = new Thread(threadTest, "A");
        Thread thread1 = new Thread(threadTest, "B");
        thread0.start();
        thread1.start();


        System.out.println(Thread.currentThread().getName());
    }
}

 

 

[ThreadTest.java]

public class ThreadTest implements Runnable {
    int testNum = 0;

    @Override
    public void run() {
        for (int i=0; i<10; i++) {
            if(Thread.currentThread().getName().equals("A")) {
                System.out.println("======================");
                testNum++;
            }
            System.out.println("Thread Name : " + Thread.currentThread().getName() + ", testNum: " + testNum);

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

 

 

[결과]

main
Thread Name : B, testNum: 0
======================
Thread Name : A, testNum: 1
======================
Thread Name : B, testNum: 1 // A일때만 ++해야되는데 B일경우에 오른 이유는 MainClass에서 thread0과 thread1가 같은 threadTest객체를 공유해서이다.
Thread Name : A, testNum: 2
======================
Thread Name : B, testNum: 2
Thread Name : A, testNum: 3
======================
Thread Name : A, testNum: 4
Thread Name : B, testNum: 3
======================
Thread Name : A, testNum: 5
Thread Name : B, testNum: 4
Thread Name : B, testNum: 5
======================
Thread Name : A, testNum: 6
======================
Thread Name : A, testNum: 7
Thread Name : B, testNum: 6
======================
Thread Name : A, testNum: 8
Thread Name : B, testNum: 7
======================
Thread Name : A, testNum: 9
Thread Name : B, testNum: 8
======================
Thread Name : A, testNum: 10
Thread Name : B, testNum: 9

 

 

 

4. 객체1개, 스레드1개

-> 위의 3번이랑 좀 다르게 객체를 구분해서 하면 A일때만 ++가된다.

ex) [MainClass.java]

ThreadTest threadTest0 = new ThreadTest();
ThreadTest threadTest1 = new ThreadTest();

Thread thread0 = new Thread(threadTest0, "A");
Thread thread1 = new Thread(threadTest1, "B");

 

 

 

5. 선거 개표 방송 예제

-> 선거 개표방송에서 지역1, 지역2, 지역3의 개표율이 엎치락 뒤치락 하는 것을 Thread를 이용하여 만들자.

ex) [MainClass.java]

public class MainClass {
    public static void main(String[] agrs) {
        VoteThread voteLocation1 = new VoteThread();
        VoteThread voteLocation2 = new VoteThread();
        VoteThread voteLocation3 = new VoteThread();

        Thread location1 = new Thread(voteLocation1, "Location1");
        Thread location2 = new Thread(voteLocation2, "Location2");
        Thread location3 = new Thread(voteLocation3, "Location3");


        location1.start();
        location2.start();
        location3.start();
    }
}

 

 

[VoteThread.java]

import java.util.Random;

public class VoteThread implements Runnable {
    int targetNum = 100; // 개표율
    int sum = 0; // 현재 몇프로가 개표율이 진행되었는지에 대한 값
    Random random = new Random(); // 개표를 진행하는 속도

    @Override
    public void run() {
        StringBuffer sb = new StringBuffer();

        while (true) {
            sum = sum + random.nextInt(10);
            sb.delete(0, sb.toString().length()); // 그래프 초기화(**로 만들어지는 그래프)

            if(sum >= targetNum) {
                sum = 100;
                for (int i=0; i
                sb.append("*");
            }
            System.out.println(Thread.currentThread().getName() + " 개표율 : " + sum + "\t: " +sb);
            break;
            } else {
                for (int i=0; i
                sb.append("*");
            }
            	System.out.println(Thread.currentThread().getName() + " 개표율 : " + sum + "\t: " + sb);
            }

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

 

 

* 이렇게 하면 객체를 공유하지않고 Thread별로 실행이 가능하다.

 

 

6. Synchronized

-> Synchronized의 사전적 의미는 통합, 동시 정도의 의미이다.

위에서 살펴본 바와 같이 JAVA 멀티스레드에서 하나의 객체에 n개의 스레드가 진행될 경우가 있다. 이런 경우 문제가 발생할 수 있다.

객체에 선언되어 있는 인스턴스 변수를 스레드에서 공유 하게 되어, 인스턴스의 값에 영향을 미치게 된다.

이런 경우를 대비해서 JAVA에서는 Synchronized라는 키워드를 사용한다.

 

* Synchronized는 먼저 수행되는 스레드의 모든 작업이 끝날 때까지 다른 스레드는 기다려야하는 방식 입니다.

ex) 식당에 가면 사람이 많아 비어있는 테이블이 없을 수 있다. 그런 경우 우리는 식당 문 앞에서 기다리다가 먼저 온 순서대로

빈자리에 앉습니다. 만약 다른 사람이 식사하고 있는 테이블에 같이 앉아서 식사를 한다면, 반찬도 공유되고, 밥도 공유되어

엉망이 될 것이다. 스레드도 마찬가지라고 생각 하면 된다.

 

스레드0 ->

스레드1 -> 객체0

스레드2 ->

 

[MainClass.java]

public class MainClass {
    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();

        Thread thread0 = new Thread(threadTest, "A");
        Thread thread1 = new Thread(threadTest, "B");
        thread0.start();
        thread1.start();

        System.out.println(Thread.currentThread().getName());
    }
}

 

 

[ThreadTest.java]

public class ThreadTest implements Runnable {
    int testNum = 0;

    @Override
    public void run() {
        for (int i=0; i<10; i++) {
            if(Thread.currentThread().getName().equals("A")) {
                System.out.println("======================");
                testNum++;
            }
            System.out.println("Thread Name : " + Thread.currentThread().getName() + ", testNum: " + testNum);


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

 

 

[결과]

main
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
Thread Name : B, testNum: 0
======================
Thread Name : A, testNum: 1
======================
Thread Name : A, testNum: 2
======================
Thread Name : A, testNum: 3
======================
Thread Name : A, testNum: 4
======================
Thread Name : A, testNum: 5
======================
Thread Name : A, testNum: 6
======================
Thread Name : A, testNum: 7
======================
Thread Name : A, testNum: 8
======================
Thread Name : A, testNum: 9
======================
Thread Name : A, testNum: 10

 

 

반응형

'Java & Kotlin > Java' 카테고리의 다른 글

JAVA 네트워크  (0) 2019.08.17
JAVA 그래픽  (0) 2019.08.16
입출력(I/O)  (0) 2019.08.16
JAVA Collections  (0) 2019.08.16
예외처리  (0) 2019.08.16
Comments