Thread
1. 단위 프로그램 (각각의 프로그램 조각)
2. main 메소드도 하나의 스레드이다. (main도 하나의 독립체로 돌고 시작한다.)
3. 스레드 종료하려면 run()를 벗어나면 된다.
main 안에 무한루프 돌면 프로그램 죽는다.
run()메소드 안에 무한루프를 만든다. (while(true))
main함수 안에 스레드.start() 걸면 run()메소드가서 실행한다. 끝나는 시점이 없다.
run()가서 일정시간 있다가 나와야한다.
run{
while(true){
일정시간 지나면 빠져나옴(위치 기억하고)
자기가 어디서 멈췄는지 기억함.
또 다시 들어가면 멈췄던 기억부터
}
}
- Thread 클래스 상속(자바는 상속 한 번밖에 안되므로 2번 방법추천)
- Runnable interface 사용
start() 걸면 Runnable(실행가능)상태에서 기다리다가 run() 돌고 빠져나오고 반복하다가
sleep이면 대기상태에 갔다가 놀다 다시 들어오고
* 우선순위
* JOIN
스레드 잠깐 멈추게 하는 것
스레드 안 하면 한 사람 처리할 때까지 다른 사람 이용못하게됨.
스레드걸면은 왔다갔다하면서 다 이용 가능해짐.
* 동기화 처리 synchronized
여러 개의 객체가 동시에 하나의 메소드에 같이 접근하려고 할 때 심각한 부하가 발생 된다.
이를 방지하기 위해 Lock을 건다.
이것을 동기화 처리라고 한다.
ex) cgv 좌석 / ATM기
스레드는 둘 다 들어올 수 있게 해준다.
각각 한 사람씩 들어오고 중간에 막아야한다.
팀원의 통장 같이 공유할 때 문제가 생김. 하나의 통장에 같이 접근하려고 할 때
Lock 걸어주는걸 - synchronized
- 함수 전체에 걸 수 있다.
public synchronized returnType 메소드명(인수형 인수, ..){
}
조금이라도 더 빠른거 먼저 실행 / 한 사람 실행하고 그 다음 사람 실행하는 것 동기화처리
2. 특정 영역만 걸 수 있다.
ATMMain.java
Thread.currentThread().getName() - 스레드의 이름만 뽑아옴.
package thread;
class ATM implements Runnable {
private long depositeMoney = 100000; //잔액
private long balance; //찾고자 하는 금액
@Override
public void run() {
System.out.println("안녕하세요 " + Thread.currentThread().getName() + "고객님");
}
}
//--------------------
public class ATMMain {
public static void main(String[] args) {
//Thread mom = new Thread(this);// static영역에서는 this값이 없고 / ATMMain이 스레드가 아님
//Thread mom = new Thread(new ATM());
//Thread son = new Thread(new ATM());//스레드 생성 (각자 스레드 만들면 충돌할 일이 없음. 각자 쓰고 있는 것 - 동기화X)
//우리는 같은 자원 이용하려는 것
ATM atm = new ATM();
Thread mom = new Thread(atm, "엄마");
Thread son = new Thread(atm, "아들");
//mom.setName("엄마");//스레드 이름 부여 - 위에 방법처럼 해도된다.
mom.start(); // 스레드 시작 -> 스레드 실행(run())
son.start(); //엄마도 run 찾아가고 아들도 run 찾아가면 동시에 run이 가능하다.
//먼저 start했으므로 엄마 아들 순이 많이 나오긴 함.
}
}
안녕하세요 엄마고객님
안녕하세요 아들고객님
Scanner scan 이용하지말고 IO 이용해보기 !!
키보드에서 돈을 치면
System.in하면 (in 자료형 - InputStream 타입)
파일로 들어오면 FileInputStream / FileOutputStream
모든 데이터가 InputStream 타입으로 들어온다. 그러므로 길을 InputStreamReader 길 만든다.
BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
readLine() → String 타입을 넘겨주므로 long타입으로 캐스팅해야함.
(long)balance = br.readLine(); - 이거 아님.
int = Integer.parseInt(String) 이런식으로
balance = Long.parseLong(br.readLine());
오버라이드 된 거에는 throws 걸면 안됨. - try-catch 이용해야함.
try {
//한줄 읽어라 String 타입을 넘겨주므로 long타입으로 캐스팅해야함.
balance = Long.parseLong(br.readLine());
}catch (IOException e) {
e.printStackTrace();
}
부모 하나만 걸어도 됨. IOException
스레드가 엄마 스레드 아들 스레드 두 개 들어오는데 통과할 때는 한 번에 한 사람씩이므로
엄마가 먼저 지나가면 그 뒤에 아들이 들어올 수 있음.
0.0몇초라도 먼저 들어온 사람 먼저 처리
그러므로 lock을 걸어줘야한다.
public synchronized void run() {
엄마가 빠져나갈 때까지는 아들이 못 들어간다.
한 번에 한사람만 들어갈 수 있는 것
@Override
public synchronized void run() {
System.out.println("안녕하세요 " + Thread.currentThread().getName() + "고객님");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("찾고자 하는 금액 입력 : ");
try {
balance = Long.parseLong(br.readLine());//한줄 읽어라 String 타입을 넘겨주므로 long타입으로 캐스팅해야함.
}catch (IOException e) {
e.printStackTrace();
}
withDraw(); //잔액계산
}
public void withDraw() {
1. 잔액은 ~~~입니다.
2. 만원 단위로 입력하세요.
3. 잔액이 부족합니다.
}
ublic void withDraw() {
if(depositeMoney >= balance) {
if(balance % 10000 == 0) {
depositeMoney -= balance;
System.out.println("잔액은 " + depositeMoney + "원 입니다.");
}else {
System.out.println("만 원 단위로 입력하세요.");
}
}else
System.out.println("잔액이 부족합니다.");
}
package thread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
class ATM implements Runnable {
private long depositeMoney = 100000; //잔액
private long balance; //찾고자 하는 금액
@Override
public synchronized void run() {
System.out.println("안녕하세요 " + Thread.currentThread().getName() + "고객님");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("찾고자 하는 금액 입력 : ");
try {
balance = Long.parseLong(br.readLine());//한줄 읽어라 String 타입을 넘겨주므로 long타입으로 캐스팅해야함.
}catch (IOException e) {
e.printStackTrace();
}
withDraw(); //잔액계산
}
public void withDraw() {
if(depositeMoney >= balance) {
if(balance % 10000 == 0) {
depositeMoney -= balance;
System.out.println("잔액은 " + depositeMoney + "원 입니다.");
System.out.println();
}else {
System.out.println("만 원 단위로 입력하세요.");
System.out.println();
}
}else {
System.out.println("잔액이 부족합니다.");
System.out.println();
}
}
}
//--------------------
public class ATMMain {
public static void main(String[] args) {
//Thread mom = new Thread(this);// static영역에서는 this값이 없고 / ATMMain이 스레드가 아님
//Thread mom = new Thread(new ATM());
//Thread son = new Thread(new ATM());//스레드 생성 (각자 스레드 만들면 충돌할 일이 없음. 각자 쓰고 있는 것 - 동기화X)
//우리는 같은 자원 이용하려는 것
ATM atm = new ATM();
Thread mom = new Thread(atm, "엄마");
Thread son = new Thread(atm, "아들");
//mom.setName("엄마");//스레드 이름 부여 - 위에 방법처럼 해도된다.
mom.start(); // 스레드 시작 -> 스레드 실행(run())
son.start(); //엄마도 run 찾아가고 아들도 run 찾아가면 동시에 run이 가능하다.
//먼저 start했으므로 엄마 아들 순이 많이 나오긴 함.
}
}
안녕하세요 엄마고객님
찾고자 하는 금액 입력 : 30000
잔액은 70000원 입니다.
안녕하세요 아들고객님
찾고자 하는 금액 입력 : 56565
만 원 단위로 입력하세요.
안녕하세요 엄마고객님
찾고자 하는 금액 입력 : 50000
잔액은 50000원 입니다.
안녕하세요 아들고객님
찾고자 하는 금액 입력 : 60000
잔액이 부족합니다.
안녕하세요 엄마고객님
찾고자 하는 금액 입력 : 30000
잔액은 70000원 입니다.
안녕하세요 아들고객님
찾고자 하는 금액 입력 : 50000
잔액은 20000원 입니다.
SynchronizedMain.java
class ATM implements Runnable { //얘는 스레드는 아님
ATM atm = new ATM();
Thread mom = new Thread(atm, "엄마"); //이렇게 해야 스레드 생성되는 것
Thread son = new Thread(atm, "아들");
위아래 차이점 확인
class Synchronized extends Thread{
Synchronized aa = new Synchronized(); //스레드 생성
얘는 상속받았기 때문에 이렇게하면 스레드 자동으로 생성된다.
System.out.println(Thread.currentThread());
현재 스레드 누구인지 확인하고 싶을 때 !
사진 설명을 입력하세요.
5 → 우선순위 - 우선권 없고 똑같이 부여한
//우선순위
//1~10까지 부여
aa.setPriority(1);
bb.setPriority(10);
cc.setPriority(5);
우선순위는 숫자 1~10까지 부여한다. (10이 우선순위 가장 높은 것)
aa.setPriority(1);
우선순위 낮게 준것
//우선순위
//1~10까지 부여
aa.setPriority(Thread.MIN_PRIORITY); //aa.setPriority(1);
bb.setPriority(Thread.MAX_PRIORITY);//bb.setPriority(10);
aa.setPriority(Thread.NORM_PRIORITY);//cc.setPriority(5);
스레드가 3개가 아니라 여러개일 때는 숫자로
but, 우선순위 의미 없다. 잘 안먹음.
Synchronized aa = new Synchronized(); //스레드 생성
Synchronized bb = new Synchronized(); //스레드 생성
Synchronized cc = new Synchronized(); //스레드 생성
공통자원 없음. 각자 스레드로 돌아가므로 충돌할 일 없다. 각각 따로따로 스레드 쥐고있다.
class Synchronized extends Thread{ //스레드 전용 클래스
private static int count;
@Override
public void run() {
for(int i=1; i<=5; i++) {
count++;
System.out.println(Thread.currentThread().getName() + " : " + count);
}
}
}
cc : 2
aa : 1
bb : 3
bb : 6
aa : 5
aa : 8
cc : 4
aa : 9
bb : 7
aa : 11
cc : 10
bb : 12
bb : 14
cc : 13
cc : 15
static은 공동의 자원으로 들어간다.
aa bb cc 각자의 스레드로 잡고있다. count는 클래스 안으로 못 들어감. count 변수는 따로 잡고 들어옴.
count 세 개의 객체가 같이 씀
count++ 이건 aa bb cc 안에 있음.
세 개의 객체가 count라는 변수 공유하고 있음 - 순서는 지멋대로 나옴.
한사람이 끝나고 나갈 때까지 기다려줘야함. 막아줘야한다.
Synchronized 걸어줘야한다.
Synchronized aa = new Synchronized(); //스레드 생성
Synchronized bb = new Synchronized(); //스레드 생성
Synchronized cc = new Synchronized(); //스레드 생성
여기서
Synchronized aa = new Synchronized(this); 이렇게 하면 안됨. 각각의 this가 다름
밑에처럼
synchronized (Synchronized.class) { 이렇게 해줘야함.
@Override
public void run() {
synchronized (Synchronized.class) {
for(int i=1; i<=5; i++) {
count++;
System.out.println(Thread.currentThread().getName() + " : " + count);
}
}
}
aa : 1
aa : 2
aa : 3
aa : 4
aa : 5
cc : 6
cc : 7
cc : 8
cc : 9
cc : 10
bb : 11
bb : 12
bb : 13
bb : 14
bb : 15
Synchronized 안에
run() {
count++;
S.o.p()
}
run()메소드가 돈다.
이게 총 3개가 돌고있다.
이때 count는 공유변수
증가하고 찍어야되는데 시간 없으면 못 찍고 쫓겨나고 여유있으면 찍고 가고 이런 현상 발생
count가 이미 증가했음에도 다른게 먼저 찍히고 순서가 뒤죽박죽
다른애가 찍지 못하게 막아야한다.
Synchronized 안에
run() {
count++;
S.o.p()
}
이거를
synchronized (Synchronized.class) { 로 막아야한다.
synchronized (this) { 이렇게 하면 안된다.
각자께 돌게 된다.
Synchronized.class 이게 세 개의 클래스의 공통점이다. 공통점으로 잡아야한다.
this는 각각 다름.
하나씩 돌도록 만든게 Synchronized - 동기화된 것!!!
ATM atm = new ATM();
Thread mom = new Thread(atm, "엄마");
Thread son = new Thread(atm, "아들");
여기선 atm이 공통점인 것처럼
package thread;
class Synchronized extends Thread{ //스레드 전용 클래스
private static int count;
@Override
public void run() {
synchronized (Synchronized.class) {
for(int i=1; i<=5; i++) {
count++;
System.out.println(Thread.currentThread().getName() + " : " + count);
}
}
}
}
//----------------
public class SynchronizedMain {
public static void main(String[] args) {
Synchronized aa = new Synchronized(); //스레드 생성
Synchronized bb = new Synchronized(); //스레드 생성
Synchronized cc = new Synchronized(); //스레드 생성
aa.setName("aa"); //스레드 이름 부여
bb.setName("bb");
cc.setName("cc");
//우선순위
//1~10까지 부여
aa.setPriority(Thread.MIN_PRIORITY); //aa.setPriority(1);
bb.setPriority(Thread.MAX_PRIORITY);//bb.setPriority(10);
aa.setPriority(Thread.NORM_PRIORITY);//cc.setPriority(5);
aa.start(); //스레드 시작 -> 스레드 실행(run())
bb.start();
cc.start();
}
}
aa : 1
aa : 2
aa : 3
aa : 4
aa : 5
cc : 6
cc : 7
cc : 8
cc : 9
cc : 10
bb : 11
bb : 12
bb : 13
bb : 14
bb : 15
SingletonMain.java
메모리에 한 번만 만드는 것
Login.java
new Login() 1번만 만드는 것
package thread;
class Singleton {
private int num = 3;
public void calc() {
num++;
}
public void disp() {
System.out.println("num = " + num);
}
}
//--------------------
public class SingletonMain {
public static void main(String[] args) {
Singleton aa = new Singleton();
aa.calc();
aa.disp();
System.out.println();
Singleton bb = new Singleton();
bb.calc();
bb.disp();
System.out.println();
Singleton cc = new Singleton();
cc.calc();
cc.disp();
System.out.println();
}
}
aa bb cc
Singleton Singleton Singleton
num num num
각각 생성
num = 4
num = 4
num = 4
private static Singleton instance;
instance 영역 잡음 static이라 하나만 잡음
if(instance == null) {
}
null인경우는 딱 한 번만 있음 - 왜냐 static 변수이므로
class Singleton {
private int num = 3;
private static Singleton instance;
public static Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) { // 한 명만 통과가능
instance = new Singleton();
}
}
return instance;
}
Singleton aa = Singleton.getInstance();
메소드를 호출한다.
맨처음 들어왔으면 null입니까? 하나만 통과한다. new해서 Singleton() 만들어짐.
instance가 만들어진거 가리키게 됨.
Singleton
num = 3;
instance에는 Singleton() 주소의 값
return instance; 주소의 값 aa에게 전달
aa에는 주소값 들어가짐.
instance, aa 둘 다 Singleton 가리킨다. 그러므로 num++ 되니까 num = 4;
num = 3;
Singleton bb = Singleton.getInstance();
null입니까? 아니니까 주소가지고 돌아옴. 그리고 다시 bb에 전달
bb도 똑같은 주소 가짐. num++ 되니까 num = 5;
num = 4
num = 5
num = 6
같이 계속 같은 메모리를 공유하는 것이 된다 !!
package thread;
class Singleton {
private int num = 3;
private static Singleton instance;
public static Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) { // 한 명만 통과가능
instance = new Singleton();
}
}
return instance;
}
public void calc() {
num++;
}
public void disp() {
System.out.println("num = " + num);
}
}
//--------------------
public class SingletonMain {
public static void main(String[] args) {
Singleton aa = Singleton.getInstance();
aa.calc();
aa.disp();
System.out.println();
Singleton bb = Singleton.getInstance();
bb.calc();
bb.disp();
System.out.println();
Singleton cc = Singleton.getInstance();
cc.calc();
cc.disp();
System.out.println();
}
}
num = 4
num = 5
num = 6
하나의 객체를 같이 쓰고 들어간다 !!!
'JAVA' 카테고리의 다른 글
DAY 13 - Collection / Generic / Interface / Exception / 입출력처리 (2024.07.19) (0) | 2024.08.12 |
---|---|
DAY 14 - 입출력처리 / 객체 직렬화 / 프로세스 / Thread (1) | 2024.08.12 |
DAY 16 - LOMBOK / 시퀀스 객체 / JDBC / DB 연결 (2024.07.24) (0) | 2024.08.09 |
DAY 17 - MEMBER (2024.07.25) (0) | 2024.08.08 |
DAY 19 - Lambda (2024.07.29) (0) | 2024.08.07 |