본문 바로가기
코딩/JAVA

JAVA 겨울방학 6일차

by sonysame 2018. 1. 3.

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