2019.01.09 스레드 Thread, 예외처리
2019. 1. 9. 16:46ㆍJAVA
#1 예외처리
① 예외의 정의
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | package com.exam; public class Test5 { public static void main(String[] args) { System.out.println("--- 프로그램 시작 ---"); // 예외: 프로그램 실행시간에 발생하는 // 예기치 못한 오류. // 코드로 처리(해결)가능한 오류. int a = 10, b = 0; // 나누는 수가 0일때 ArithmeticException발생안되게 int result = 0; if (b == 0) { System.out.println("0으로 나눌수 없음"); } else { result = a / b; } System.out.println("나눗셈 결과: "+result); System.out.println("--- 프로그램 정상종료 ---"); } // main() } | cs |
② 예외처리의 방법
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | package com.exam; public class Test6 { public static void main(String[] args) { System.out.println("--- 프로그램 시작 ---"); // 예외 처리 // try - catch - finally // RuntimeException(실행시간예외)은 // 자바에서 예외처리를 강제하지 않는다. // 그러므로 예외처리가 선택적이다. // RuntimeException - ArithmeticException // - NullPointerException // - ... int a = 10, b = 2; // b = 0 int result = 0; String str = ""; int[] array = { 1, 2, 3 }; try { // 예외가 발생할것 같은 문장 result = a / b; // ArithmeticException int length = str.length(); // NullPointerException array[3] = 4; // ArrayIndexOutOfBoundsException } catch (ArithmeticException e) { // 작은 글러브 e.printStackTrace(); } catch (NullPointerException e) { e.printStackTrace(); } catch (RuntimeException e) { // 큰 글러브 e.printStackTrace(); } catch (Exception e) { // 아주 큰 글러브 e.printStackTrace(); } finally { System.out.println("예외발생 여부 상관없이 정리작업"); } System.out.println("나눗셈 결과: "+result); System.out.println("--- 프로그램 정상종료 ---"); } // main() } | cs |
③ 예외처리의 방법2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | package com.exam; class ExcepTest { /*int a; int b; a = 10; b = 20; System.out.println(a+b);*/ int methodD() { // try - finally 는 예외처리랑 관계없음 // try { return 10; } finally { System.out.println("출력"); } } void methodC() throws Exception { methodB(); } void methodB() throws Exception { methodA(50); } void methodA(int num) throws Exception { if (num < 100) { throw new Exception("num값이 100보다 작다."); // 1) 예외를 내부적으로 직접처리하는 방법 // try { // throw new Exception("num값이 100보다 작다."); // } catch (Exception e) { // e.printStackTrace(); // } } } } public class Test7 { public static void main(String[] args) /*throws Exception*/ { ExcepTest test = new ExcepTest(); try { test.methodC(); } catch (Exception e) { e.printStackTrace(); } int num = test.methodD(); System.out.println(num); System.out.println("--- 프로그램 정상종료 ---"); } // main(); } | cs |
#2 스레드 Thread
① Thread의 기본형태
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | package com.example; /* 스레드 Thread */ class Go { void go() { while (true) {// 무한반복 System.out.println("go"); } } }// Go() class Come { void come() { while (true) {// 무한반복 System.out.println("come"); } } }// Come() public class Test3 { public static void main(String[] args) { Go g = new Go(); Come c = new Come(); g.go(); c.come(); }// main() } | cs |
②Multi Thread 방법1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | package com.example; /* 멀티 스레드 Multi Thread 방법1*/ class Go1 extends Thread{ // 작업스레드의 시작 (진입점)메소드는 run()이다. @Override public void run() { go1(); } void go1() { while (true) {// 무한반복 System.out.println("go"); } } }// Go1() class Come1 extends Thread{ @Override public void run() { come1(); } void come1() { while (true) {// 무한반복 System.out.println("come"); } } }// Come2() public class Test4 { /* < 주(main) 스레드와 보조(Daemon) 스레드 > 스레드는 주 스레드와 보조 스레드로 나뉜다. 주 스레드는 1개라도 동작 중이면 프로그램 종료가 되지 않는다. 하지만, 보조 스레드는 주 스레드를 보조하는 역할이므로 주 스레드가 종료되면 보조 스레드도 함께 종료된다.*/ public static void main(String[] args) { /* 멀티 스레드 생성방법1. 1. Thread 클래스 상속 run() 메소드 오버라이딩 스레드 객체.start(); 스레드 시작*/ /* 스레드는 Thread타입의 객체이다. * 스레드 객체가 생성되면 해당 객체만의 스택이 생성된다. */ Go1 g1 = new Go1(); // 스택 생성후 준비됨 Come1 c1 = new Come1(); // 스택 생성후 준비됨 /*스레드 제어는 사용자가 하지않고 JVM이 제어한다. JVM한테 스레드 시작을 부탁하는 메소드가 start()이다.*/ g1.start(); c1.start(); // ▶출력 : come과 go가 반복되며 출력된다. }//main() } | cs |
②Multi Thread 방법2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | package com.example; /* 멀티 스레드 Multi Thread 방법2: Runnable 인터페이스 방식1 */ // [작업 내용]을 가진 클래스 class goTask implements Runnable{ @Override public void run() { while(true) { System.out.println("go"); } } }//goTask() class comeTask implements Runnable{ @Override public void run() { come(); } void come() { while(true) { System.out.println("come"); } } }//comeTask() public class Test5 { public static void main(String[] args) { /* 멀티 스레드 생성방법2 * 2. Runnable 인터페이스 구현 run() 메소드 오버라이딩 Thread 객체 생성 -> Runnable 구현객체를 사용하도록 전달 스레드 객체.start() 스레드 시작*/ // Thread는 일꾼 객체 , Runnable구현 객체는 일꾼이 할 일이 정의되어 있는 객체 Runnable goTask = new goTask(); //업 캐스팅 Thread t1 = new Thread(goTask); // 일꾼에게 할 일을 등록, 콜백패턴 Runnable comeTask = new comeTask(); Thread t2 = new Thread(comeTask); t1.start(); // 일꾼이 일을 시작하다록 JVM에게 부탁 t2.start(); // JVM은 스레드 준비가 완료되면 스레드 객체의 run()메소드를 호출 }//main() } | cs |
③Multi Thread 방법3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | package com.example; /* 멀티 스레드 Multi Thread 방법3 :Runnable 인터페이스 방식2*/ public class Test6 { public static void main(String[] args) { // Runnable 방식으로 스레드 사용 // 함수적 인터페이스 : 추상메소드 1개 가진 인터페이스 → 람다식 활용가능 new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println("작업스레드 " + i); } } }).start(); //람다식 활용 new Thread(()->{ for(int i= 0; i<3; i++) { System.out.println("람다식 작업 스레드"+i); } }).start(); //메인 스레드 for(int i=0; i<3; i++) { System.out.println("메인스레드 "+i); } }//main() } | cs |
#3 스레드 Thread의 종류 및 우선순위
① 메인 스레드(main thread)와 보조 스레드(daemon thread)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | package com.example; /*메인 스레드와 보조스레드의 위치*/ import java.awt.Toolkit; public class Test7 { public static void main(String[] args) { /* * 프로그램이 실행되면 main thread가 생성되고 main thread에서 main()메소드가 호출함 */ Thread thread = new Thread(() -> { // run()메소드가 생략되어있다 Toolkit toolkit = Toolkit.getDefaultToolkit(); for (int i= 0; i < 5; i++) { toolkit.beep(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.setDaemon(true);// 보조스레드 설정 thread.start(); /* main thread가 끝난 상태에서 Daemon thread가 실행되지 않기 때문에 Daemon thread가 먼저 선언되어야 한다.*/ for (int i = 0; i < 5; i++) { System.out.println("띵~"); try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } // 예외처리가필요 } }// main() } | cs |
② 스레드의 이름
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | package com.example; /* 스레드의 이름*/ public class Test8 { public static void main(String[] args) { Thread mainThread = Thread.currentThread(); System.out.println(mainThread.getName()); // 스레드의 이름 받아오기 mainThread.setName("major thread"); // 스레드의 이름 재정의 System.out.println(mainThread.getName()); final Thread t1 = new Thread(new Runnable() { @Override public void run() { for(int i=0; i<2; i++) { System.out.println(i+""); } } }); System.out.println(t1.getName()); t1.setName("작업스레드1"); t1.start(); }//main() } | cs |
④ 스레드 우선순위
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.example; public class Test9 { public static void main(String[] args) { System.out.println(Thread.currentThread().getName()); /* 스레드 우선순위 :우선순위 방식에서 우선순위는 1에서 10까지 부여되는데, 1이 가장 낮은 우선순위,10이 가장 높은 우선순위이다. 우선순위를 부여하지 않으면 모든 클레스들은 기본적으로 5의 우선순위를 할당받는다. */ System.out.println(Thread.currentThread().getPriority()); // 우선순위 값을 int로 리턴 System.out.println(Thread.MAX_PRIORITY); // 최대 우선순위 :10 System.out.println(Thread.MIN_PRIORITY); // 최소 우선순위 :1 System.out.println(Thread.NORM_PRIORITY); // 중간 우선순위 :5 Thread.currentThread().setPriority(8); // 우선순위를 설정 }//main() } | cs |
#4 스레드를 활용한 GUI 시계
① RootController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | package com.exam.app.view; import java.net.URL; import java.util.ResourceBundle; import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Button; import javafx.scene.control.Label; public class RootController implements Initializable { @FXML private Label label; @FXML private Button btnStart, btnStop; private int count = 0; // 카운트 필드 private Thread t; @Override public void initialize(URL location, ResourceBundle resources) { btnStart.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { startCount(event); } }); btnStop.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { if (t == null) { return; } else { t.interrupt(); // 권장되는 스레드 종료방식 } } }); public void startCount(ActionEvent event) { t = new Thread(new Runnable() { @Override public void run() { startCount1(); } }); t.setDaemon(true); // 보조 스레드 지정 t.start(); }// startCount() public void startCount1() { while (true) { if (Thread.interrupted()) { break; } Platform.runLater(new Runnable() { @Override public void run() { label.setText(count + ""); } }); try { Thread.sleep(1000); /* * 일시정지되는 동안 Interrupted()가 호출되면 InterruptedException이 발생됨 */ } catch (InterruptedException e) { break; // 인터럽트 발생시 발생종료 } count++; } }// run1 } | cs |
② Main class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | package com.exam.app; import java.io.IOException; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; public class MainApp extends Application { @Override public void start(Stage primaryStage) { Scene scene= null; try { // 단축키 : alt + shift + z // fxml 파일로부터 컨테이너 가져오기 Parent root =FXMLLoader.load(getClass().getResource("view/Root.fxml")); scene = new Scene(root); // 화면 생성, import 단축키 :ctrl +shift +o } catch (IOException e) { e.printStackTrace(); } // 윈도우 창에 부착 primaryStage.setScene(scene); primaryStage.setTitle("창 제목"); primaryStage.setResizable(false); primaryStage.show(); }//start() public static void main(String[] args) { launch(args); } } | cs |
cf) 버튼동작없이 화면출력만 할 경우
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Thread t1 = new Thread(() -> { while (true) { // ▼ int->String으로 변환 ,사용자의 눈에 보이는 컨트롤에 대한 수정은 작업스레드에서 할수 없다. Platform.runLater(() -> { label.setText(String.valueOf(count)); }); try { Thread.sleep(1000);// 1000ms , 1초동안 멈추었다 다시실행 } catch (InterruptedException e) { e.printStackTrace(); } count++; } }); /* * main Thread(주스레드)가 종료될 때 같이 종료되게 하기 위해 Daemon Thread(보조 스레드)로 설정해준다. */ t1.setDaemon(true);// 보조스레드로 설정 t1.start(); | cs |
'JAVA' 카테고리의 다른 글
2019.01.14 JavaFx 활용하기 (0) | 2019.01.14 |
---|---|
2018.01.11 멀티 스레드의 활용 (0) | 2019.01.11 |
2019.01.09 컬렉션 프레임워크:Map,Set,list (0) | 2019.01.09 |
2019.01.07 기본API클래스 예제 (0) | 2019.01.07 |
2019.01.07 문자열위치, 문자위치,StringBuffer, StringBuilder,Wrapper클래스,Math,Random 클래스,Date , Calendar 클래스,컬렉션 프레임워크 (0) | 2019.01.07 |