ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 210423_3~4(멀티스레드)
    JAVA(Sol)(정리대기중..언젠가) 2021. 4. 23. 13:14

    멀티스레드

     

    1. 스레드 Thread : 어떤 로직이나 함수의 실행 단위.

     

    a(){ }

                                  (cpu자원)

    a( ) 3번 호출  |---a()---|---a()---|---a()---|   ===> 단일스레드 - 지금까지 사용법

                                                                    각각의 함수가 자원을 독점

                       (cpu자원)

    a( ) 3번 호출  |---a()---|

                          |---a()---|

                             |---a()---| 

                              --   동시성을 갖고 실행되는구간===> 멀티스레드(동시에 실행되는 것처럼 보임)

                                                                                 자원을 공유해서 사용한다

     

    멀티스레드의 장점 

    [웹서버 - 하나의 클라이언트 처리시간 1초라고 가정]

      동시에 1000명이 접속했다. 1000번째 사람의 앞에 999명의 즉999초 동안 기다려야 자신의 처리가 돌아온다

      그런데, 멀티스레드가 되면, 웹서버가 자원을 돌아가면서 모든 클라이언트들에게 처리를 조금씩 돌아가면서

      하게되므로 훨씬 빠른속도로 자신의 처리를 할 수가 있다.

     

    돈이 되는 프로그램은 다 멀티다. 게임서버, db서버, 웹서버, 채팅 서버 ...~


    적용방법

     

     

    Runnable 인터페이스 적용하거나

       |

    Thread 클래스를 상속받아서  // Thread클래스는 Runnable을 구현한 구현 클래스이다.

       |

    MyThread { // 다중상속으로 Thread상속을 받을수없을때 Runnable 인터페이스를 적용한다.

      ↓

    run( ) { 

    멀티로 구현하고자 하는 로직이나 함수를 run 메서드로 감싼다

        }

    }

     

     

    기억!

    Runnable Thread
    run() run(), start()가 있다.

    결론 : 실행하려면 start() 가 포함하는 Thread 객체(인스턴스)를 만들어야한다

     

    호출

    MyThread mt = new MyThread ();

    mt.run() ;  <=== 호출불가. run()은 구현만 할 수 있고, 호출이 불가하다. 그래도 호출하면 단일스레드로 작동됨(주의

    mt.start() ; <=== start() 라는 메서드로 호출한다.

     

    원리

      start( ) <==== jvm에 요청 등록 === >run() 호출

      run( ) 은 jvm에 의해서 호출되므로 callback method라고 한다.

    package chapter16;
    
    //스레드가 없는경우
    class GenClass {
    	private int num; //필드1
    	private String name; //필드2
    
    	public GenClass(String a, int b) { //생성자
    		name = a;
    		num = b;
    	}
    
    	public void start() { //메서드1
    		for (int i = 0; i < num; i++) //로직
    			System.out.println(name + "." + i);
    	}
    
    }
    
    public class NonThread {
    
    	public static void main(String[] args) {
    		GenClass t1 = new GenClass("first", 5);
    		GenClass t2 = new GenClass("second", 5);
    		GenClass t3 = new GenClass("third", 5);
    
    		t1.start(); //단일스레드  jvm start()와 관련x
    		t2.start();
    		t3.start();
    	}
    
    }
    //first.0
    //first.1
    //first.2
    //first.3
    //first.4
    //second.0
    //second.1
    //second.2
    //second.3
    //second.4
    //third.0
    //third.1
    //third.2
    //third.3
    //third.4
    
    package chapter16;
    
    //멀티스레드 적용
    class MyThread extends Thread { //스레드상속
    	private int num;
    	private String name;
    
    	public MyThread(String a, int b) { //생성자
    		name = a;
    		num = b;
    	}
    
    	public void run() {   // 멀티스레드구현 run()메서드
    		for (int i = 0; i < num; i++)
    			System.out.println(name + ":" + i);
    	}
    }
    
    public class ThreadTest1 {
    
    	public static void main(String[] args) {
    		MyThread t1 = new MyThread("first", 1000); //인스턴스1 
    		MyThread t2 = new MyThread("second", 1000); //인스턴스2
    		MyThread t3 = new MyThread("third", 1000); //인스턴스3
    
    		t1.start(); // jvm start
    		t2.start(); // 단 한번이라도 처리가 섞이면 멀티스레드이다
    		t3.start();
    	}
    
    }
    //second:0
    //third:0
    //first:0
    //third:1
    //second:1
    //third:2
    //first:1
    //third:3
    //second:2
    //third:4
    //....~~

     

    package chapter16;
    
    //Runnable 인터페이스를 통한 멀티스레드
    class ThreadOne implements Runnable { // Runnable 인터페이스상속//ThreadOne가 Runnable을 적용한 타겟클래스이다
    	private int num;
    	private String name;
    
    	public ThreadOne(String a, int b) {
    		name = a;
    		num = b;
    	}
    
    	public void run() { // 멀티스레드 구현
    		for (int i = 0; i < num; i++)
    			System.out.println(name + ":" + i);
    	}
    }
    
    public class TreadTest2 {
    
    	public static void main(String[] args) {
    		Thread t1 = new Thread(new ThreadOne(("first"), 1000));
    		// Thread는 Runnable을 구현한 클래스이다
          	 	// Runnable로 만들면 하위객체를 호출하지못하기때문에 형변환도해야한다
    		Thread t2 = new Thread(new ThreadOne(("second"), 1000));
    		Thread t3 = new Thread(new ThreadOne(("third"), 1000));
            //생성자안의 파라미터에 Runnable의 인자(상속받은 ThreadOne)를 넣어서 사용하기때문
         	// =new Tread(new 러너블타겟()) ->new 러너블타겟()이 인자를 두개갖고있기때문에()가 또들어간것
    
    
    
    		t1.start();
    		t2.start();
    		t3.start();
    	}
    
    }
    

    동시성 구간을 크게하기

    앞의 사실에서 알수있듯이, 첫 스레드에서 잠시 쉬어갈때 다른 스레드가 시작된다.

    그렇다면, 강제로 쉬게 하면 더 동시성 구간이 커지지 않을까?

     

    그래서 sleep(ms);메서드 ms는 1/1000초 동안 쉬도록 하면 골고루 섞인다.

    package chapter16;
    
    //동기화없는 경우
    class RunThread extends Thread {
    
    	public RunThread(String name) {
    		super(name); //Thread의 String을 인자로 갖는 생성자
    	}
    
    	public void run() {
    		for (int i = 1; i <= 500; i++) {
    			if (i % 50 == 0)
    				System.out.println("Thread[" + getName() + "]:" + i);
    			                                 //getName은 상속받은 Thread에서 온것
    
    		}
    	}
    }
    
    public class SchedulingTest1 {
    
    	public static void main(String[] args) {
    		Thread[] t = new RunThread[2]; //스레드 배열
    
    		t[0] = new RunThread("ONE");
    		t[1] = new RunThread("TWO");
    
    		t[0].start();
    		t[1].start();
    
    	}
    
    }
    //Thread[TWO]:50
    //Thread[TWO]:100
    //Thread[TWO]:150
    //Thread[ONE]:50
    //Thread[ONE]:100
    //Thread[TWO]:200
    //Thread[ONE]:150
    //Thread[ONE]:200
    //Thread[TWO]:250
    //Thread[ONE]:250
    //Thread[TWO]:300
    //...~ 동시성이거의없다
    package chapter16;
    
    //동기화를 처리한경우
    class RunThread2 extends Thread {
    	public RunThread2(String name) {
    		super(name);
    	}
    
    	public void run() {
    		for (int i = 1; i <= 500; i++) {
    			if (i % 50 == 0) {
    				System.out.println("Thread[" + getName() + "] :" + i);
    				try {
    					sleep(1); // 1/1000초에 한번 쉼 //동시성을 크게하기위함
    					System.out.println("");
    				} catch (Exception e) {
    				}
    			}
    		}
    	}
    }
    
    public class SchedulingTest2 {
    
    	public static void main(String[] args) {
    		Thread[] t = new RunThread2[3];
    
    		t[0] = new RunThread2("☆");
    		t[1] = new RunThread2("★");
    		t[2] = new RunThread2("◆");
    
    		t[0].start();
    		t[1].start();
    		t[2].start();
    	}
    
    }
    //Thread[★] :50
    //Thread[☆] :50
    //Thread[◆] :50
    //				//sleep발생구간
    //
    //Thread[☆] :100
    //
    //Thread[★] :100
    //Thread[◆] :100
    //Thread[★] :150
    //
    //
    //Thread[◆] :150
    //Thread[☆] :150
    //
    //
    //
    //Thread[◆] :200
    //Thread[★] :200
    //Thread[☆] :200
    //
    //
    //Thread[★] :250
    //
    //Thread[◆] :250
    //Thread[☆] :250
    //...~
    

     

     

     

     

Designed by Tistory.