Java::Thread

class

값, 상태 -> 멤버변수 

Process(연산, 조건, 반복) -> method(메소드)

입출력과 Thread는 항상 예외가 발생 할 수 있다

그래서 항상 TryCatch문으로 처리를 해주어야한다

 

Thread는 멀티스레딩을 통해 동시에 여러 작업을 수행할 수 있도록 지원하는 클래스이다

멀티스레딩을 사용하면 CPU 자원을 더 효율적으로 활용하고 응답성을 개선할 수 있다

package p09_Thread;

public class Ex01Thread {
  public static void main(String[] args) {
    for (int i = 10; i >0 ; i--) {
      System.out.println(i);
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        throw new RuntimeException(e);
      }
    }
  }
}

 

 

Thread의 장점으로 별도의 흐름을 생성 가능하고 

자원을 절약 할 수있다

 

Thread 를 생성하는 방법

 

1)Thread를 상속

2) Runnable을 implement

 

package p09_Thread;

public class Ex01Thread {
  public static void main(String[] args) {
   int input = Integer.parseInt(JOptionPane.showInputDialog("빨간선(0), 파란선(1) 중에 선택하세요!"));
    for (int i = 10; i >0 ; i--) {
      System.out.println(i);
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        throw new RuntimeException(e);
      }
    }
     if (input == answer) {
      System.out.printf("input : %d , answer : %d || 살았다!", input, answer);
    } else {
      System.out.printf("input : %d , answer : %d || 꽝!", input, answer);
    }
  }
}

 

Thread를 사용하지 않고 

import javax.swing.*;
import java.util.Random;

public class Ex01Thread {
  public static void main(String[] args) {
    Bomb bomb = new Bomb();
    //Thread를 상속 받으면 그 자체로 start()를 적용할 수 잇다
    //bomb.start(); //Thread 동작 시작!

    //Runnalbe 을 implement 하면 Thread() 생성자 안에
    //매개변수로 전달해야만 생성 가능
    new Thread(bomb).start();
    int input = Integer.parseInt(JOptionPane.showInputDialog("빨간선(0), 파란선(1) 중에 선택하세요!"));
    bomb.choice(input);;
  }
}
class Bomb extends Thread {
  int answer = (int) (Math.random() * 2);
  boolean state_b = false;

  //run : Thread의 동작을 할 때 정의한 메서드
  @Override
  public void run() {
    state_b = true;
    for (int i = 10; i > 0; i--) {
      if (state_b) {
        System.out.println(i);
        try {
          Thread.sleep(1000);
          if(!state_b) break;
          System.out.println("돌아가는중");
        } catch (InterruptedException e) {
          throw new RuntimeException(e);
        }
      }
    }
  }

  void choice(int input) {
    if (input == answer) {
      System.out.printf("input : %d , answer : %d || 살았다!", input, answer);
    } else {
      System.out.printf("input : %d , answer : %d || 꽝!", input, answer);
    }
    state_b = false;
  }
}

 

이러한 스레드를 사용하려면

여러 스레드가 공유 자원에 접근할 때 동기화 과정에서 문제가 발생 할 수있다

' synchronized '키워드를 사용하여 데이터의 일관성을 유지하게 만든다


데이터 동기화(Synchronized)

 

Java에서 동기화를 위해 사용되는 키워드로, 멀티스레딩 환경에서

여러 스레드가 공유 자원에 동시에 접근할 때 발생할 수 있는 문제를 방지합니다.

synchronized 키워드를 사용하여 한 번에 하나의 스레드

특정 블록 또는 메서드에 접근할 수 있도록 합니다.

 

아래의 코드는 사용자의 balance 라는 주어진 값에서

100~300이라는 랜덤한 숫자를 주어

숫자만큼 값을 빼는 코드이다

package p09_Thread;

public class Ex07Synchronized {

  public static void main(String[] args) {
    Customer customer = new Customer();
    new Thread(customer).start();
  }
}

class Account {
  int balance = 1000;

  public int getBalance() {
    return balance;
  }

  public void withdraw(int money) {
    if (balance >= money) {
      try {
        Thread.sleep(300);
      } catch (Exception e) {
      }
      balance -= money;
    }
  }
}

class Customer implements Runnable {
  Account acc = new Account();

  @Override
  public void run() {
    while (acc.getBalance() > 0) {
      int money = (int) (Math.random() * 3 + 1) * 100;
      acc.withdraw(money);
      System.out.println("잔액 : " + acc.getBalance());
    }
  }
}

 

Thread()를 사용해서  동시성 및 병렬 처리를 하게 되면

다음과 같은 문제가 발생한다

 

package p09_Thread;

public class Ex07Synchronized {

  public static void main(String[] args) {
    Customer customer = new Customer();
    //인터페이스는 재정의한 메서드만 가져와서 사용할 수 있다
    //즉, customer 안에이있는 run() 만 사용함
    new Thread(customer).start(); 
    new Thread(customer).start();
  }
}

class Account {
  int balance = 1000;

  public int getBalance() {
    return balance;
  }

  public void withdraw(int money) {
    if (balance >= money) {
      try {
        Thread.sleep(300);
      } catch (Exception e) {
      }
      balance -= money;
    }
  }
}

class Customer implements Runnable {
  Account acc = new Account();

  @Override
  public void run() {
    while (acc.getBalance() > 0) {
      int money = (int) (Math.random() * 3 + 1) * 100;
      acc.withdraw(money);
      System.out.println("잔액 : " + acc.getBalance());
    }
  }
}

 

 

동시에 값을 들고오면서 처리를 하여

0 보다 작은 값이 나오는 경우가 발생한다

synchronized public void withdraw(int money) {
  if (balance >= money) {
    try {
      Thread.sleep(300);
    } catch (Exception e) {
    }
    balance -= money;
  }
}

값을 처리하는 구간인 withdraw 에 synchronized 를 작성해

공유 자원에 동시에 접근할 때 발생할 수 있는 문제를 해결해준다

package p09_Thread;

public class Ex07Synchronized {

  public static void main(String[] args) {
    Customer customer = new Customer();
    //인터페이스는 재정의한 메서드만 가져와서 사용할 수 있다
    //즉, customer 안에이있는 run() 만 사용함
    new Thread(customer).start();
    new Thread(customer).start();
  }
}

class Account {
  int balance = 1000;

  public int getBalance() {
    return balance;
  }

  synchronized public void withdraw(int money) {
    if (balance >= money) {
      try {
        Thread.sleep(300);
      } catch (Exception e) {
      }
      balance -= money;
    }
  }
}

class Customer implements Runnable {
  Account acc = new Account();

  @Override
  public void run() {
    while (acc.getBalance() > 0) {
      int money = (int) (Math.random() * 3 + 1) * 100;
      acc.withdraw(money);
      System.out.println("잔액 : " + acc.getBalance());
    }
  }
}

 

synchronized 키워드는 멀티스레드 환경에서 안전하게 자원을 공유하기 위해 사용된다