-
프로세스, 쓰레드 Thread프로그래밍/JAVA 자바 2021. 9. 5.반응형
간단히 말하자면 동작하고 있는 프로그램 => 프로세스
프로세스는 보통 한개의 작업을 함.
그러나 쓰레드를 이용하면 하나의 프로세스에서 두가지 이상의 일을 동시에 할 수 있음.
멀티 태스킹 생각하면 이해가 쉬움
ex) 밥을 먹으면서 핸드폰을 하는 행위도 쓰레드라 볼 수 있음.
스레드 클래스를 상속 받기
package threadEx; public class Ex001_Thread { public static void main(String[] args) { MyThread1 t = new MyThread1(); t.start(); // 스레드 시작 try { for(int i=1; i<=10; i++) { System.out.println("main ->" + i); Thread.sleep(100); } } catch (Exception e) { e.printStackTrace(); } System.out.println("main 종료"); // main은 프로그램의 진입점이며, main이 종료되어도 프로그램은 종료 안될 수 있음. // 프로그램의 종료 시점은 모든 독립 스레드가 종료되는 시점이다. } } //스레드 구현 방법 1 // Thread 클래스를 상속 받아서 run() 메소드를 override 한다. // Thread 클래스를 상속 받은 클래스의 객체를 생성해서 start() 메소드 호출한다. class MyThread1 extends Thread { @Override public void run() { int n = 0; try { while(n < 20) { n++; System.out.println(getName() + "->"+n); sleep(500); // 지정 시간(단위 ms)동안 스레드 실행이 일시 중지 } } catch (InterruptedException e) { e.printStackTrace(); } } }
일단 쓰레드 상속 받은 클래스를 하나 만든다.
그리고 run() 메소드를 오버라이드 재정의 해야 한다.
재정의 내용은 단순하게 1~20까지 출력하는 내용이고
중간에 sleep(500)<<은 한번의 반복이 끝나면 0.5초 쉬겠다는 의미
그리고 메인 쪽으로 가서 쓰레스 클래스 만들고 .start()로 1~20까지 출력하는 반복문 실행.
이후에 메인쪽 코드에 1~10 까지 출력하는 코드 작성
한번의 반복이 끝나면 쓰레드를 0.1초 쉬게한다.
이러면 메인쪽 반복문과 쓰레드 반복문이 동시에 작동한다.
Runnable 인터페이스 이용한 스레드
package threadEx; public class Ex002_Runnable { public static void main(String[] args) { MyThread2 th = new MyThread2(); Thread t = new Thread(th); t.start(); try { for(int i=1; i<=10; i++) { System.out.println("main ->" + i); Thread.sleep(100); } } catch (Exception e) { e.printStackTrace(); } System.out.println("main 종료"); } } // 스레드 구현 방법 2 // 1.Runnable 인터페이스를 구현하는 클래스를 만들어 run() 메소드를 override 한다. // 2.Runnable 인터페이스 구현 클래스 객체 생성. // 3. Thread 클래스를 객체를 생성하며, Thread 객체를 생성할때 생성자의 인자에 2)번에서 생성한 객체를 넘긴다. // 4. Thread 클래스를 객체의 start() 메소드를 호출한다. class MyThread2 implements Runnable { @Override public void run() { int n = 0; try { while(n < 20) { n++; System.out.println(Thread.currentThread().getName() + "->" + n); Thread.sleep(500); } } catch (Exception e) { e.printStackTrace(); } } }
새로운 클래스를 만들고 Runnable 인터페이스를 참조하고 run()을 오버라이드한다.
비교를 위해서 현재 스레드에 표시될 이름을 지정해준다.
그리고 메인으로 올라가서 아래 작성한 클래스 객체 생성해주고
스레드 객체를 새로 만든다음에 인자에 넣어준다.
그리고 .start()로 시작
스레드의 반복문과 메인의 반복문은 엄연히 다른 것임.
익명 클래스로 스레드 구현
package threadEx; public class Ex003_Runnable { public static void main(String[] args) { // 스레드 구현 방법 3 // 익명 클래스를 이용한 스레드 구현 Thread t = new Thread( new Runnable() { @Override public void run() { try { for(int n = 1; n <= 20; n++) { System.out.println("스레드 -> " + n); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } }); t.start(); try { for(int i = 1; i <= 10; i++) { System.out.println("메인 -> " + i); Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("메인 종료 !!!"); } }
이번에는 클래스를 새로 만들지 않고 바로 메인 소스에 스레스 객체를 만들고 인자에 직접 Runnable()을 넣어버린다.
마찬가지로 run() 재정의하고 스레드 작성
꼭 })<< 옆에 ; 세미콜론 붙여야 한다.
그리고 start()로 시작
이후에 메인에 반복문 하나를 추가한다.
이러면 클래스 작성없이 스레드를 추가 할 수있다.
람다를 이용한 스레드 구현
package threadEx; public class Ex004_Runnable { public static void main(String[] args) { // 스레드 구현방법 4 : 람다를 이용한 스레드 구현 Thread t = new Thread( () -> { try { for(int n = 1; n <= 20; n++) { System.out.println("스레드 -> " + n); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } }); t.start(); try { for(int i = 1; i <= 10; i++) { System.out.println("메인 -> " + i); Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("메인 종료 !!!"); } }
람다는 아직 안배웠으니 이런게 있다는 것만 보고 넘어간다.
날짜 실시간 갱신하기
package threadEx; import java.util.Calendar; public class Ex005_Runnable { public static void main(String[] args) { // TODO Auto-generated method stub Thread t = new Thread(new MyThread5()); t.start(); } } class MyThread5 implements Runnable{ @Override public void run() { String str; while(true) { Calendar cal = Calendar.getInstance(); str = String.format("%tF %tT", cal, cal); System.out.println(str); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
Calender 객체를 이용하기 위해서 .getInstance()를 이용해야 한다.
그리고 문자열 형식 지정하기 위해서 String.format을 사용한다.
%tF = 현재의 날짜를 년-월-일 형식으로 출력함.
%tT = 현재의 시간을 시:분:초 형식으로 출력한다.
Daemon Thread 데몬 스레드
= 다른 스레드에게 도움을 주기 위한 용도
= 메인 스레드가 종료되면 데몬 스레드의 작업이 끝나지 않아도 프로그램이 종료됨.
package threadEx; /* * - 독립 스레드 * 메인은 프로그램의 시작점이지 종료점은 아니다. * 메인 스레드가 종료 되어도 독립 스레드의 작업이 완료될 때 까지 프로그램은 종료 되지 않음. * - 데몬 스레드 * 다른 스레드에게 도움을 주기 위한 스레드 * 메인 스레드가 종료되면 데몬 스레드의 작업이 완료 되지 않아도 프로그램은 종료 됨. */ public class Ex006_Daemon { public static void main(String[] args) { // MyThread6 t1 = new MyThread6(); MyThread6 t2 = new MyThread6(); MyThread6 t3 = new MyThread6(); // 스레드를 데몬으로 만듬. t1.setDaemon(true); t2.setDaemon(true); t3.setDaemon(true); t1.start(); t2.start(); t3.start(); try { t1.join(); // 스레드가 종료 될때까지 대기 t2.join(); t3.join(); } catch (Exception e) { e.printStackTrace(); } System.out.println("메인 종료"); } } class MyThread6 extends Thread { @Override public void run() { for(int i=1; i<=20; i++) { System.out.println(getName() + "=>"+i); } try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } } }
데몬으로 지정하기 위해서 start 전에 setDaemon(true)를 해주자.
t1.join()을 하게되면 t1스레드가 끝날때가지 기다리고 t1스레드가 끝나면 현재 스레드를 진행 한다는 의미이다.
Priority
우선순위 부여 가능
package threadEx; public class Ex007_Priority { public static void main(String[] args) { // TODO Auto-generated method stub MyThread7 t1 = new MyThread7("A"); MyThread7 t2 = new MyThread7("B"); MyThread7 t3 = new MyThread7("C"); t1.setPriority(Thread.MIN_PRIORITY); // 1 t2.setPriority(Thread.MAX_PRIORITY); // 10 t1.start(); t2.start(); t3.start(); } } class MyThread7 extends Thread { public MyThread7(String name) { super(name); } @Override public void run() { for(int i=1; i<=20; i++) { //System.out.println(getName() + "=>" + i); System.out.println(this); // 스레드명, 우선순위, 그룹 } } }
Join
package threadEx; public class Ex008_join { public static void main(String[] args) { // TODO Auto-generated method stub MyThread8 t = new MyThread8(); System.out.println("start 전 - Alive : "+ t.isAlive()); //alive는 스레드가 죽었나 살았나 판별 t.start(); System.out.println("start 후 - Alive : "+ t.isAlive()); try { t.join(); // 스레드가 종료 할때까지 대기 } catch (Exception e) { e.printStackTrace(); } System.out.println("Alive : "+ t.isAlive()); System.out.println("메인 종료"); } } class MyThread8 extends Thread { @Override public void run() { try { for(int i=1; i<=20; i++) { System.out.println(getName()+"=>"+i); join(500); // 스레드를 1/1000초 만큼 기다린다. } } catch (Exception e) { e.printStackTrace(); } } }
join은 아까의 설명과 더불어 시간을 지정해 줄 수 도 있다.
몇 가지의 1초의 타입
package threadEx; import java.util.concurrent.TimeUnit; public class Ex009_NanoTime { public static void main(String[] args) { // TODO Auto-generated method stub try { long start = System.currentTimeMillis(); TimeUnit.SECONDS.sleep(1L); // 1초 TimeUnit.MILLISECONDS.sleep(1000L); // 1초 TimeUnit.MICROSECONDS.sleep(1000000L); // 1초 TimeUnit.NANOSECONDS.sleep(1000L); // 1 microseconds long end = System.currentTimeMillis(); System.out.println("Sleep : "+ (end-start)+"ms"); } catch (Exception e) { e.printStackTrace(); } } }
ThreadStop
interrupt()
package threadEx; public class Ex010_ThreadStop { // interrupt() 메소드를 이용한 스레드 종료 // interrupt() 메소드를 호출해서 인터럽트를 받은 스레드가 // sleep(), join(), wait() 같은 메소드를 호출하여 대기 상태에 있으면 해당 스레드는 // InterruptedException 예외가 발생하여 대기 상태에서 빠져 나온다. // 만약 InterruptedException 예외를 발생하지 않는 메소드를 호출한 경우에는 // Thread.interrupted() 메소드를 호출해서 인터럽트 되었는지 여부를 검사한다. // Thread.isInterrupted() // InterruptedException 예외가 발생하면 false 반환 public static void main(String[] args) { // TODO Auto-generated method stub Thread t = new Thread(new MyThread10()); t.start(); try { Thread.sleep(3000); } catch (Exception e) { // TODO: handle exception } //t.stop(); // 스레드는 종료가 되지만 마지막 스레드 종료가 안나옴 t.interrupt(); System.out.println("메인 종료"); } } class MyThread10 implements Runnable { @Override public void run() { long n=0; try { while(true) { n++; System.out.println("스레드 : " + n); Thread.sleep(500); } } catch (InterruptedException e) { System.out.println("인터럽트 됨"); } System.out.println("스레드 종료"); } }
스레드 종료는 stop보단 interrupt가 더 좋다.
반응형'프로그래밍 > JAVA 자바' 카테고리의 다른 글
스레드(3) Timer 클래스 / wait (0) 2021.09.07 Thread 스레드 (2) / synchronized (0) 2021.09.06 자바DB / CallableStatement (0) 2021.09.02 자바DB연동 / PreparedStatement 활용 예제 (0) 2021.08.30 입출력 스트림 마무리 (0) 2021.08.29