1. Multi Processing
CPU안에 Core라는게 있는데 실제 프로그램은 core가 실행해준다.
Single Core=>cpu안에 core가 1개 있다. 따라서 single core에서는 멀티프로세싱이 일어날 수가 없다.
multi processing은 core가 두개 이상일 때 의미를 가지는 용어
2. Multi Tasking
Core의 개수와는 상관이 없다.
시분할(Time Slicing)을 통해 시간을 쪼개서 짧은 시간동안 여러 프로그앰을 번갈아 실행시켜 마치 동시에 실행시키는 효과를 얻는 것
3. Multi Threading
하나의 프로그램이 여러 단위 Thread로 구성되어 있고
이 Thread가 마치 동시에 실행이 되는 것처럼 동작시킬 수 있다
4. 프로세스
OS에서 실행중인 하나의 Application
OS로부터 실행에 필요한 메모리를 할당 받아서 Application코드를 실행
5. 동시성(concurrency) vs 병렬성(parallelism)
concurrency: 논리적인 개념, 1~100까지 더하는 프로그램 작성->1~25, 26~50, 51~75, 76~100->이렇게 4부분으로 나누어서 동시에 진행해서 프로그램을 처리
parallelism: 물리적인 개념
6.
-Thread개념
하나의 프로그램내에서 여러개의 실행흐름을 파생
Thread를 이용하면 프로그램의 효율을 높일 수 있다.
single thread->단일, 순차 처리
다중 thread를 이용하면 concurrent처리를 할 수 있다.
대신 thread를 파생시키는 overhead가 생긴다.
-Thread를 만드는 방법
1) Thread class를 직접 상속해서 새로운 class 작성
//Thread는 instance형태로 존재하고
//당연히 클래스가 있어야 한다. 특정 클래스(Thread)를 상속해서 클래스를 만들어야 한다.
class MyThread extends Thread{
//나중에 thread scheduler에 의해 선택되면 특수한 method가 실행되게 된다.
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName());
}
}
2) Runnable interface를 구현(implement)해서 새로운 class 작성
//Runnable interface를 이용해서 클래스를 작성
class MyRunnable implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName());
}
}
3) anonymous inner class를 이용해서 thread 생성
//anonymous inner class를 이용해서 thread를 생성
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
4) lambda 축약형
//축약형으로 표현할 수 있다->java8이상에서만 사용 lambda
Thread t2=new Thread(() ->{
System.out.println(Thread.currentThread().getName());
});
-Thread실행
start()라는 method로 실행
Thread Scheduler에게 부탁->해당 Thread 좀 실행시켜줘
-Thread종료
run()의 실행이 끝나면 Thread가 종료
7. 코딩
package JavaThread;
public class Exam01_Basic {
public static void main(String[] args) {
// TODO Auto-generated method stub
//현재 Thread의 이름을 화면에 찍어보아요
//Thread Instance를 생성
Thread thread=new MyThread();
// 단순히 Thread instance를 만든거고 이게 아직 실행되지는 않는다.
thread.start();
// main thread는 run 상태
//Thread scheduler는 고민
//main thread를 계속 run상태로 실행할지, 아니면 main thread를 runnable상태로 전환(core가 떠남)시키고
//새로운 Thread를 run 상태로 전환할지를 고민
// 해당 Thread가 runnable살태로 전환
// Thread Scheduler에게 나중에 시간나면 실행시켜 달라고 요청=>결과를 받아오지 않는다.(blocking되지 않는다.)
Runnable runnable=new MyRunnable();
//Runnable interface를 구현한 객체를 생성, 아직 Thread가 아니다.
Thread t=new Thread(runnable);
t.start();
//Runnable안에 run() method가 overriding이 안되었기 때문에 직접 인스턴스를 생성할 수 없다.
//anonymous inner class를 이용해서 thread를 생성
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName());
}
}
);
//축약형으로 표현할 수 있다->java8이상에서만 사용 lambda
Thread t2=new Thread(() ->{
System.out.println(Thread.currentThread().getName());
});
System.out.println(Thread.currentThread().getName());
}
}
//1. Thread는 instance형태로 존재하고
//당연히 클래스가 있어야 한다. 특정 클래스(Thread)를 상속해서 클래스를 만들어야 한다.
class MyThread extends Thread{
//나중에 thread scheduler에 의해 선택되면 특수한 method가 실행되게 된다.
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName());
}
}
//2. Runnable interface를 이용해서 클래스를 작성
class MyRunnable implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName());
}
}
package JavaThread;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
//javaFX를 이용하여 화면에 창을 띄워 보아요
//Application이라는 클래스가 추상 클래스->추상 메소드가 있다
public class Exam02_javaFX extends Application{
private TextArea textarea;
private Button startBtn;
@Override
public void start(Stage primaryStage) throws Exception {
// 화면 구성을 작성.
//primaryStage가 창이다
//동서남북중앙 5개의 영역으로 분할할때 사용하는 클래스가 있다.
BorderPane root=new BorderPane();
root.setPrefSize(700,500);
//글상자를 하나 만든다
textarea=new TextArea();
root.setCenter(textarea);
//버튼들이 위차할 패널하나 생성
FlowPane bottom=new FlowPane();
bottom.setPrefSize(700, 50);
//bottom에 뭔가 붙을 때 여백을 주어서 붙여요!
bottom.setPadding(new Insets(10,10,10,10));
startBtn=new Button("Thread 시작");
startBtn.setPrefSize(100, 30);
startBtn.setOnAction(event->{
//버튼이 클릭되면 이 코드를 수행한다.
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10;i++) {
try{
Thread.sleep(1000);
} catch(InterruptedException e) {
e.printStackTrace();
}
//화면에 있는 컴퍼넌트(textarea)를 제어하려면 또 다시 Thread를 이용해야 한다
Platform.runLater(()->{
textarea.appendText("첫번째 Thread!!\n");
});
}
}
});
t1.start();
Thread t2=new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10;i++) {
try{
Thread.sleep(1000);
} catch(InterruptedException e) {
e.printStackTrace();
}
//화면에 있는 컴퍼넌트(textarea)를 제어하려면 또 다시 Thread를 이용해야 한다
Platform.runLater(()->{
textarea.appendText("두번째 Thread!!\n");
});
}
}
});
t2.start();
});
//하위 패널에 버튼을 부착!
bottom.getChildren().add(startBtn);
root.setBottom(bottom);
//장면을 만들어야 한다.
Scene scene=new Scene(root);
//해당 장면을 창에 붙여서 우리 눈에 보이게 만들어야 한다.
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
System.out.println("main thread 종료!!");
launch();
}
}
package JavaThread;
import java.util.Random;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
public class Exam03_Race extends Application{
private TextField field1;
private ProgressBar bar1;
private ProgressIndicator indicator1;
private TextField field2;
private ProgressBar bar2;
private ProgressIndicator indicator2;
private TextField field3;
private ProgressBar bar3;
private ProgressIndicator indicator3;
private TextArea textarea;
private Button btn;
@Override
public void start(Stage primaryStage) throws Exception {
//일단 화면을 5영역으로 분할
BorderPane root=new BorderPane();
//화면의 크기를 설정
root.setPrefSize(700, 500);
FlowPane center=new FlowPane();
center.setPadding(new Insets(20,20,20,20));
center.setPrefSize(700, 450);
//이름입력상자 생성
field1=new TextField();
field1.setPrefSize(100, 60);
//progressBar 생성
bar1=new ProgressBar();
bar1.setPrefSize(450, 60);
//progressIndicator 생성
indicator1=new ProgressIndicator();
indicator1.setPrefSize(100,60);
field2=new TextField();
field2.setPrefSize(100, 60);
//progressBar 생성
bar2=new ProgressBar();
bar2.setPrefSize(450, 60);
//progressIndicator 생성
indicator2=new ProgressIndicator();
indicator2.setPrefSize(100,60);
field3=new TextField();
field3.setPrefSize(100, 60);
//progressBar 생성
bar3=new ProgressBar();
bar3.setPrefSize(450, 60);
//progressIndicator 생성
indicator3=new ProgressIndicator();
indicator3.setPrefSize(100,60);
center.getChildren().add(field1);
center.getChildren().add(bar1);
center.getChildren().add(indicator1);
center.getChildren().add(field2);
center.getChildren().add(bar2);
center.getChildren().add(indicator2);
center.getChildren().add(field3);
center.getChildren().add(bar3);
center.getChildren().add(indicator3);
textarea=new TextArea();
textarea.setPrefSize(500, 100);
center.getChildren().add(textarea);
btn=new Button("시작!!");
btn.setPrefSize(300,50);
btn.setOnAction(event->{
//버튼이 눌리면 Thread를 3개 만들어서 각각 실행
Thread t1= new Thread(new MyProgressRunnable(field1,bar1,indicator1));
t1.start();
Thread t2= new Thread(new MyProgressRunnable(field2,bar2,indicator2));
t2.start();
Thread t3= new Thread(new MyProgressRunnable(field3,bar3,indicator3));
t3.start();
});
center.getChildren().add(btn);
root.setCenter(center);
//화면생성
Scene scene=new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
//javaFX application Thread를 생성
//이 Thread가 start()호출!
launch();
}
}
class MyProgressRunnable implements Runnable{
private TextField field;
private ProgressBar bar;
private ProgressIndicator indicator;
public MyProgressRunnable(TextField field, ProgressBar bar, ProgressIndicator indicator) {
super();
this.field = field;
this.bar = bar;
this.indicator = indicator;
}
@Override
public void run() {
// Thread의 동작방식
// 난수를 발생시켜서 해당 난수값을 progressbar에 누적
// 만약 progressbar값이 1.0이상이면 그만하고 해당 사용자 이름을 textarea에 출력
// 루프를 반복적으로 수행해야되고 sleep을 이용해서 조금씩 쉬었다가 적용해야 될 듯 보여요.
// 난수를 발생시킬때는 Random class를 이용
Random random=new Random();
double sum=0.0;
random.nextDouble();//실수값을 뽑아내는데 0.0~1.0사이의 값을 추출
while(true) {
sum+=random.nextDouble()*0.1;
final double k=sum;
Platform.runLater(()->{
bar.setProgress(k);
indicator.setProgress(k);
});
try {
Thread.sleep(100);
}catch(Exception e) {
e.printStackTrace();
}
if(sum>=1.0) {
break;
}
}
}
}
8. 동기화
공유객체를 일반적으로 Thread가 이용하게 되는데
주의할 점->동기화 문제가 발생
의도치 않게 다른 Thread에 의해서 공유객체의 상태가 변경
-synchronized keyword를 이용
-synchronized block을 이용해 critical section을 내가 설정!
package JavaThread;
//Thread에 의해서 사용될 공유객체
class Shared{
private int number;
public Shared() {
}
public int getNumber() {
return number;
}
//만약 method에 synchronized keyword를 이용하면
//method전체가 임계영여그로 할당(Critical Section)
//만약 synchronized block을 이용하면 내가 임계영역을 설정
public synchronized void setNumber(int number) {
synchronized(this)
{
this.number=number;
try {
Thread.sleep(2000);
System.out.println("number : "+getNumber());
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
class MyRunnable1 implements Runnable{
private Shared obj;
private int number;
public MyRunnable1() {
// TODO Auto-generated constructor stub
}
public MyRunnable1(Shared obj, int number) {
super();
this.obj = obj;
this.number = number;
}
//Thread 2개가 동시에 run이 수행되고 공용객체를 이용해서 2개의 Thread가 동시에 공용객체의 field의 값을 setting하고 출력하려 함
@Override
public void run() {
// TODO Auto-generated method stub
obj.setNumber(number);
}
}
public class Exam05_SynchronizeDOS {
public static void main(String[] args) {
Shared obj=new Shared();
Thread t1=new Thread(new MyRunnable1(obj,100));
Thread t2=new Thread(new MyRunnable1(obj,200));
t1.start();
t2.start();
}
}
창에 출력
package JavaThread;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
//javaFX를 이용하여 화면에 창을 띄워 보아요
//Application이라는 클래스가 추상 클래스->추상 메소드가 있다
public class Exam04_Synchronization extends Application{
private TextArea textarea;
private Button startBtn;
@Override
public void start(Stage primaryStage) throws Exception {
// 화면 구성을 작성.
//primaryStage가 창이다
//동서남북중앙 5개의 영역으로 분할할때 사용하는 클래스가 있다.
BorderPane root=new BorderPane();
root.setPrefSize(700,500);
//글상자를 하나 만든다
textarea=new TextArea();
root.setCenter(textarea);
//버튼들이 위차할 패널하나 생성
FlowPane bottom=new FlowPane();
bottom.setPrefSize(700, 50);
//bottom에 뭔가 붙을 때 여백을 주어서 붙여요!
bottom.setPadding(new Insets(10,10,10,10));
startBtn=new Button("Thread 시작");
startBtn.setPrefSize(100, 30);
startBtn.setOnAction(event->{
//공유객체를 생성
SharedObject obj=new SharedObject(textarea);
Thread t1=new Thread(new SynchRunnable(obj,100));
Thread t2=new Thread(new SynchRunnable(obj,200));
t1.start();//run호출
t2.start();
});
//하위 패널에 버튼을 부착!
bottom.getChildren().add(startBtn);
root.setBottom(bottom);
//장면을 만들어야 한다.
Scene scene=new Scene(root);
//해당 장면을 창에 붙여서 우리 눈에 보이게 만들어야 한다.
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
System.out.println("main thread 종료!!");
launch();
}
}
class SharedObject{
private int number;
private TextArea textarea;
public SharedObject(TextArea textarea) {
this.textarea=textarea;
}
public int getNumber(){
return number;
}
//자바에서는 공유자원에 대한 접근을 키워드 하나로 제어할 수 있다
//synchronized keyword로 제어
public synchronized void setNumber(int number) {
this.number=number;
//thread가 공유객체의 setter를 이용해서 값을 세팅
try {
Thread.sleep(2000);
//2초 기다렸다가 textarea에 number값을 출력
Platform.runLater(()->{
textarea.appendText("숫자 : "+number+"\n");
});
}catch(Exception e) {
e.printStackTrace();
}
}
}
//Runnable interface를 구현한 class를 작성
class SynchRunnable implements Runnable{
private SharedObject sharedObject;
private int number;
public SynchRunnable(SharedObject sharedObject, int number) {
super();
this.sharedObject = sharedObject;
this.number = number;
}
public SynchRunnable() {
// TODO Auto-generated constructor stub
}
//이 클래스로 thread를 생성할거고, 당연히 공유객체에 대한 reference는 field로 등장
@Override
public void run() {
// TODO Auto-generated method stub
sharedObject.setNumber(number);
}
}
'코딩 > JAVA' 카테고리의 다른 글
JAVA 겨울방학 8일차 (0) | 2018.01.04 |
---|---|
JAVA 겨울방학 7일차 (0) | 2018.01.04 |
겨울방학 JAVA 4일차 (0) | 2017.12.29 |
겨울방학 JAVA 3일차 (0) | 2017.12.28 |
겨울방학 JAVA 1일차 (0) | 2017.12.27 |