Thread
1. Thread Lifecycle
2. Race Condition
3. DeadLock
------------
1. Thread Lifecycle
public class SingleThread {
public static void main(String[] args) {
System.out.println(Thread.currentThread());
}
}
출력:
Thread[main,5,main]
//[이름, 우선순위, 그룹]
-----------------------------------
public class OneThread {
public static void main(String[] args) {
OneThread ot = new OneThread();
for(int i = 0 ; i < 10 ; i++) System.out.println("main() --> " + i);
ot.run(); //running -> dead run은 os스케쥴러가 일함
System.out.println("end main()");
}
void run(){
for(int i = 0 ; i < 10 ; i++) System.out.println("run() --> " + i);
}
}
출력:
main() --> 0
main() --> 1
main() --> 2
main() --> 3
main() --> 4
main() --> 5
main() --> 6
main() --> 7
main() --> 8
main() --> 9
run() --> 0
run() --> 1
run() --> 2
run() --> 3
run() --> 4
run() --> 5
run() --> 6
run() --> 7
run() --> 8
run() --> 9
end main()
//run을 호출하기전에는 run은 실행하지 않아. 쓰레드가 오직 하나만 있는 경우임. 순서 예측 가능.
-------------------------------
public class TwoThread extends Thread{
public static void main(String[] args) {
TwoThread tt = new TwoThread();
for(int i = 0 ; i < 10 ; i++) System.out.println("main() --> " + i);
tt.start(); //new->runnable 상태로. 메모리에 올리는 상태?
System.out.println("end main()");
}
@Override
public void run(){
for(int i = 0 ; i < 10 ; i++) System.out.println("run() --> " + i);
}
}
출력:
main() --> 0
main() --> 1
main() --> 2
main() --> 3
main() --> 4
main() --> 5
main() --> 6
main() --> 7
main() --> 8
main() --> 9
end main()
run() --> 0
run() --> 1
run() --> 2
run() --> 3
run() --> 4
run() --> 5
run() --> 6
run() --> 7
run() --> 8
run() --> 9
//위코드와는 다르게 main이 끝나고 end main()을 찍어준 후에 run에가서 일함. 100번돌리면 100번 같지 않을 수 있다.
----아래의 코드로 바꿔주면
public class TwoThread extends Thread{
public static void main(String[] args) {
TwoThread tt = new TwoThread();
for(int i = 0 ; i < 10 ; i++) System.out.println(Thread.currentThread().getName() + "--> " + i);
tt.start();
System.out.println("end main()");
}
@Override
public void run(){
for(int i = 0 ; i < 10 ; i++) System.out.println(Thread.currentThread().getName() + " --> " + i);
}
}
출력:
main--> 0
main--> 1
main--> 2
main--> 3
main--> 4
main--> 5
main--> 6
main--> 7
main--> 8
main--> 9
end main()
Thread-0 --> 0
Thread-0 --> 1
Thread-0 --> 2
Thread-0 --> 3
Thread-0 --> 4
Thread-0 --> 5
Thread-0 --> 6
Thread-0 --> 7
Thread-0 --> 8
Thread-0 --> 9
각자활동하는 쓰레드의 이름이 다른 것을 볼 수 있다.
--------------------------------------------
//Thread의 자식
public class CreateThread extends Thread {
public static void main(String[] args) {
CreateThread ct = new CreateThread();
CreateThread ct1 = new CreateThread();
System.out.println(Thread.currentThread());
ct.start();
ct1.start();
}
@Override
public void run(){
System.out.println(Thread.currentThread());
}
}
//상속을 받으면 - 멀티상속이 안돼. 자식은 private빼고 다 볼 수 있다.
출력:
Thread[main,5,main]
Thread[Thread-0,5,main]
Thread[Thread-1,5,main]
-----------------------------------------------
public class CreateThread1 implements Runnable {
public static void main(String[] args) {
CreateThread1 ct = new CreateThread1();
CreateThread1 ct1 = new CreateThread1();
Thread t = new Thread(ct, "Duncan"); //runnable은 start메소드를 실행할 수없어서, 쓰레드를 선언하여.
Thread t1 = new Thread(ct1, "Sally"); //이름을 줄 수 있다.
t.start();
t1.start();
System.out.println(Thread.currentThread());
}
@Override
public void run() {
System.out.println(Thread.currentThread());
}
}
//단점은 내가 직접할 수 없고, 쓰레드를 선언하여 사용.
//상속을 받지 않았다는 점이 장점.
출력:
Thread[main,5,main]
Thread[Sally,5,main]
Thread[Duncan,5,main]
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
쓰레드를 안전하게 죽이는 방법.
//boolean type variable 이용하자.
//돌때마다 또 돌까요? 라고 물어보는 방법. 라인을 다돌아야 죽일 수 있다.
public class StopThread {
public static void main(String[] args) {
Demo d = new Demo();
Thread t = new Thread(d);
t.start();
System.out.println("Thread is starting...");
try{
Thread.sleep(1000); //1초간 대기
}catch(InterruptedException ex){}
System.out.println("Thread stop...");
d.stop();
}
}
class Demo implements Runnable{
private boolean isStop; //boolean변수는 기본초기값이 false
void stop(){
this.isStop = true;
}
@Override
public void run(){
//Thread 가 해야할 일
while(true){
try{
Thread.sleep(100); //0.1초 대기 후
}catch(InterruptedException ex){}
System.out.println("I'm alive...");
if(this.isStop) break;
}
System.out.println("I'm dead...");
}
}
출력:
Thread is starting...
I'm alive...
I'm alive...
I'm alive...
I'm alive...
I'm alive...
I'm alive...
I'm alive...
I'm alive...
I'm alive...
Thread stop...
I'm alive... <-여기서 바로 안죽고 한번 더찍어주는 이유는 if문에서 죽었는지 확인하는 시간필요. 그래서 단점은 바로죽지않는다는.
I'm dead...
--------------------------------------
//Exception 이용하자.
//100라인까지 가는상황에서 20라인에서 죽일 수 있다.장점: 바로 죽일 수 있다.
public class StopThread1 {
public static void main(String[] args) {
Demo1 d = new Demo1();
Thread t = new Thread(d);
t.start();
System.out.println("Thread is starting...");
try{
Thread.sleep(100); //0.1초간 대기
}catch(InterruptedException ex){}
System.out.println("Thread stop...");
t.interrupt(); //InterruptedException throw
}
}
class Demo1 implements Runnable{
@Override
public void run(){
//Thread 가 해야할 일
try{
while(true){
Thread.sleep(10); //0.01초
System.out.println("I'm alive...");
}
}catch(InterruptedException ex){
System.out.println("I'm dead...");
}
}
}
출력:
Thread is starting...
I'm alive...
I'm alive...
I'm alive...
I'm alive...
I'm alive...
I'm alive...
I'm alive...
I'm alive...
I'm alive...
Thread stop...
I'm dead...
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
데몬 쓰레드
public class DaemonThread {
public static void main(String[] args) {
Thread t = new Thread(){
@Override
public void run(){
//Thread 가 해야할 일
try {
Thread.sleep(20000); //20초 대기
} catch (Exception e) {}
System.out.println("Thread is over...");
}
};
t.start();
try {
Thread.sleep(5000); //5초간 대기
} catch (Exception e) {}
System.out.println("main() is over...");
}
}
출력:
main() is over...
Thread is over...
//메인은 5초뒤에 중지. 쓰레드는 그 뒤로 15초뒤에 중지.
//메인이 끝나고 프로그램이 끝나는 것이 아니라, 안의 모든 쓰레드가 끝나야 종료.
--------------만약
t.start()위에 t.setDaemon(true);를 써주면 이 프로그램은 데몬쓰레드를 의미한다.
데몬쓰레드는 메인이 끝이면 프로그램이 끝이다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
Join
public class JoinDemo {
public static void main(String[] args) {
Thread t = new Thread(){
@Override
public void run(){
//Thread 가 해야할 일
try {
Thread.sleep(5000); //5초간 대기
System.out.println("I'm Thread...");
} catch (Exception e) {} //5초가 보장하지 않을 경우의 익셉션
}
};
t.start();
try{
t.join(); //t라는 thread가 끝나면 join하겠다. ()안에 숫자넣으면 그 시간만큼.
}catch (Exception e){}
System.out.println("I'm main()");
}
}
출력:
I'm Thread...
I'm main()
//t.join을 써주지 않으면 당연히 I'm main()이 먼저 출력되지만, join을 써줌으로써 출력순서가 바뀜.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
Priority
public class PriorityDemo {
public static void main(String[] args) {
System.out.println("MAX : " + Thread.MAX_PRIORITY);
System.out.println("MIN : " + Thread.MIN_PRIORITY);
System.out.println("NORM : " + Thread.NORM_PRIORITY);
}
}
출력:
MAX : 10
MIN : 1
NORM : 5
-----------------
public class PriorityDemo {
public static void main(String[] args) {
//System.out.println("MAX : " + Thread.MAX_PRIORITY);
//System.out.println("MIN : " + Thread.MIN_PRIORITY);
//System.out.println("NORM : " + Thread.NORM_PRIORITY);
Test t = new Test("Duncan");
t.setPriority(Thread.MIN_PRIORITY);
Test t1 = new Test("Sally");
t1.setPriority(Thread.MAX_PRIORITY);
t.start();
t1.start();
}
}
class Test extends Thread{
Test(String name){
super(name);
}
@Override
public void run(){
System.out.println(Thread.currentThread());
}
}
출력:
Thread[Duncan,1,main]
Thread[Sally,10,main]
//우선순위를 10을줬음에도 출력이 바뀌지 않았다. priority는 잘 안되는 것을 볼 수 있다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
sleep과 yield
public class SleepDemo extends Thread{
SleepDemo(String name) { super(name); }
public static void main(String[] args) {
SleepDemo sd = new SleepDemo("Duncan");
SleepDemo sd1 = new SleepDemo("Sally");
sd.start(); sd1.start();
}
@Override
public void run(){
//Thread가 해야할 일
for(int i = 0 ; i < 20 ; i++){
//Thread.yield();
try{
Thread.sleep(1000);
}catch(Exception e){}
System.out.println(Thread.currentThread().getName() + " --> " + i);
}
}
}
//처음에 sleep이나 yield가 없는경우
Duncan --> 0
Duncan --> 1
Sally --> 0
Duncan --> 2
Sally --> 1
Duncan --> 3
이렇게 시작하고 순서없이 출력된다. 이 결과는 실행때마다 출력 순서가 다르다.
출력부분 위에 Thread.yield(); 를 추가해주면 서로 양보하기 때문에 위와 같이 순서없이 출력되는 것 같다.
그러면 sleep을 주면 출력후 1초간 쉬기 때문에
Duncan --> 0
Sally --> 0
Duncan --> 1
Sally --> 1
Duncan --> 2
Sally --> 2
Duncan --> 3
Sally --> 3
위와 같이 하나씩 출력하는 것을 볼 수 있다. 하지만 가끔 Duncan이 두번연속 출력되는 것도 있지만 숫자는 00 11 이런식으로 바뀌지 않는다.
--------------------------------------------------------
쓰레드를 이용하여 시계만들기
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics;
import java.util.Calendar;
import javax.swing.JFrame;
public class MyClock extends Thread {
private JFrame f;
private MyCanvas mc;
private Container con;
private MyClock(){
this.f = new JFrame("My Digital Clock");
this.con = this.f.getContentPane();
mc = new MyCanvas();
}
private void display(){
this.f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //끝내면 끝나게.
Font font = new Font("Loma", Font.BOLD, 50);
this.mc.setFont(font);
this.con.setLayout(new BorderLayout());
this.con.add("Center", this.mc);
this.f.setSize(500,200);
this.f.setLocationRelativeTo(null);
this.f.setVisible(true);
}
private class MyCanvas extends Canvas{
private Calendar cal;
@Override
public void paint(Graphics g){
cal = Calendar.getInstance();
String str = String.format("%tT", cal); //'T'를 찍으면 "%tH:%tM:%tS"를 자동으로
g.drawString(str, 50, 50);
}
}
@Override
public void run(){
//Thread가 해야할 일
try{
while(true){
Thread.sleep(1000);
this.mc.repaint();
}
}catch(InterruptedException e) {}
}
public static void main(String[] args) {
//new MyClock().display(); //display와 쓰레드를 시작해줘야 하기 때문에 이렇게 쓰면 복잡해지니. 하나쓸때만 편함.
MyClock clock = new MyClock();
clock.display();
clock.start();
}
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
Thread group
public class ThreadGruopDemo {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getThreadGroup());
ThreadGroup group1 = new ThreadGroup("Group1");
ThreadGroup group2 = new ThreadGroup(Thread.currentThread().getThreadGroup(),"Group2"); //부모그룹, 내그룹이름
ThreadGroup group3 = new ThreadGroup(group1, "Group3");
Thread t1 = new Thread(group1, "Thread1");
Thread t2 = new Thread(group2, "Thread2");
Thread t3 = new Thread(group3, "Thread3");
System.out.println(t1);
System.out.println(t2);
System.out.println(t3);
int count = Thread.currentThread().getThreadGroup().activeCount();
int groupCount = Thread.currentThread().getThreadGroup().activeGroupCount();
System.out.println("count = " + count);
System.out.println("group count = " + groupCount);
Thread.currentThread().getThreadGroup().list(); //list()는 void형임
}
}
출력:
java.lang.ThreadGroup[name=main,maxpri=10]
Thread[Thread1,5,Group1]
Thread[Thread2,5,Group2]
Thread[Thread3,5,Group3]
count = 1
group count = 3
java.lang.ThreadGroup[name=main,maxpri=10]
Thread[main,5,main]
java.lang.ThreadGroup[name=Group1,maxpri=10]
java.lang.ThreadGroup[name=Group3,maxpri=10]
java.lang.ThreadGroup[name=Group2,maxpri=10]
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
Thread는 stack을 제외하고 heap, method area, context pool 에서는 자원을 공유함.
자원공유때문에 race condition문제가 발생.
Syncronized
전혀 동기화처리가 되지않은 ATM
public class ATM implements Runnable{
private int balance;
ATM(){
this.balance = 10000;
}
private void withdraw(int howmuch){
if(this.balance <= 0){
System.out.print("[" + Thread.currentThread().getName() +"] --> ");
System.out.println(" --> 잔액이 없습니다.");
}else{
this.balance -= howmuch;
System.out.println("[" + Thread.currentThread().getName() +"] -->" + this.balance);
}
}
@Override
public void run(){
//Thread 가 해야할 일
for(int i = 0 ; i < 10 ; i++){
try{
Thread.sleep(1000);
}catch(InterruptedException ex){}
if(this.balance > 0) withdraw(1000);
else break;
}
}
}
public class ATMDemo {
public static void main(String[] args) {
ATM atm = new ATM();
Thread mother = new Thread(atm, "mother");
Thread son = new Thread(atm, "son");
mother.start();
son.start();
}
}
출력:
[mother] -->9000
[son] -->9000
[mother] -->8000
[son] -->7000
[mother] -->6000
[son] -->5000
[son] -->4000
[mother] -->4000
[son] -->3000
[mother] -->2000
[son] -->1000
[mother] -->0
//돌릴때마다 다르게 나옴. 여기서는 12번 인출을 해서 은행입장에서는 손해가 보게된다.
-----------------------------
version up - ATM v-1
public class ATM1 implements Runnable{
private int balance;
ATM1(){
this.balance = 10000;
}
private /*synchronized*/ void withdraw(int howmuch){ //메소드를 동기화할 때 이렇게 사용.
if(this.balance <= 0){
System.out.print("[" + Thread.currentThread().getName() +"] --> ");
System.out.println(" --> 잔액이 없습니다.");
}else{
this.balance -= howmuch;
System.out.println("[" + Thread.currentThread().getName() +"] -->" + this.balance);
}
}
@Override
public void run(){
//Thread 가 해야할 일
for(int i = 0 ; i < 5 ; i++){
synchronized(this){ //동기화 블럭
try{
Thread.sleep(1000);
}catch(InterruptedException ex){}
if(this.balance > 0) withdraw(1000);
else break;
}
}
}
}
public class ATMDemo {
public static void main(String[] args) {
ATM1 atm = new ATM1();
Thread mother = new Thread(atm, "mother");
Thread son = new Thread(atm, "son");
mother.start();
son.start();
}
}
출력:
[mother] -->9000
[mother] -->8000
[mother] -->7000
[mother] -->6000
[mother] -->5000
[son] -->4000
[son] -->3000
[son] -->2000
[son] -->1000
[son] -->0
//동시에 하나의 쓰레드만 사용하여, 엄마먼저 끝내고, 아들이 실행. 엄마가 실행되는동안 다른 쓰레드는 대기상태.
//락을 걸면 좋은 점은 한 쓰레드만 들어올 수 있다. 쓰는 쓰레드는 열쇠를 들고 있다가 다쓰면 반납하고, 그 다음 쓰레드가 사용한다.
---------------------------
ATM v-2
데드락문제 해결
public class ATM2 implements Runnable{
private int balance;
ATM2(){
this.balance = 10000;
}
private /*synchronized*/ void withdraw(int howmuch){ //메소드를 동기화할 때 이렇게 사용.
if(this.balance <= 0){
System.out.print("[" + Thread.currentThread().getName() +"] --> ");
System.out.println(" --> 잔액이 없습니다.");
}else{
this.balance -= howmuch;
System.out.println("[" + Thread.currentThread().getName() +"] -->" + this.balance);
}
}
@Override
public void run(){
//Thread 가 해야할 일
for(int i = 0 ; i < 10 ; i++){
synchronized(this){ //동기화 블럭
try{
Thread.sleep(1000);
}catch(InterruptedException ex){}
if(this.balance > 0) withdraw(1000);
else break;
if(this.balance == 2000 || this.balance == 4000 || this.balance == 6000 || this.balance == 8000) {
try{
this.wait();
}catch(InterruptedException e) {}
} else{
this.notify();
}
}
}
}
}
public class ATMDemo {
public static void main(String[] args) {
ATM2 atm = new ATM2();
Thread mother = new Thread(atm, "mother");
Thread son = new Thread(atm, "son");
mother.start();
son.start();
}
}
출력:
[mother] -->9000
[mother] -->8000
[son] -->7000
[son] -->6000
[mother] -->5000
[mother] -->4000
[son] -->3000
[son] -->2000
[mother] -->1000
[mother] -->0
//2000원마다 쓰레드를 변경.
===============================================
public class Calc {
private Customer customer;
public Calc(Customer customer){
this.customer = customer;
}
public void calc(){
String pCode = this.customer.getPcode();
this.customer.setRegion(this.getPlaceName(pCode));
int distance = this.getPlaceDistance(pCode);
String gender = (customer.getJumin2().trim().charAt(0) == '1') ? "남자" : "여자";
this.customer.setGender(gender);
String tCode = customer.getTscode().trim().substring(0,2);
String tName = this.getTrainName(tCode);
customer.setTname(tName);
String seatName = this.getSeatName(tCode);
customer.setSname(seatName);
String ppCode = customer.getPpcode();
customer.setKind(this.getKindName(ppCode));
double rate = this.getRate(ppCode);
int danga = this.getDanga(tName, seatName);
int price = distance * danga;
int premium = (int)(price * rate);
customer.setPrice(premium);
int charge = price - premium;
customer.setCharge(charge);
}
private String getPlaceName(String pCode){
String pName = null;
switch(pCode){
case "CA": pName = "서울"; break;
case "CB": pName = "부산"; break;
case "CC": pName = "대구"; break;
case "CD": pName = "광주"; break;
}
return pName;
}
private int getPlaceDistance(String pCode){
int distance = 0;
switch(pCode){
case "CA": distance = 400 ; break;
case "CB": distance = 50 ; break;
case "CC": distance = 110 ; break;
case "CD": distance = 180 ; break;
}
return distance;
}
private String getTrainName(String tCode){
String tName = null;
switch(tCode){
case "TA" : tName = "새마을호" ; break;
case "TB" : tName = "무궁화호" ; break;
case "TC" : tName = "통일호"; break;
}
return tName;
}
private String getSeatName(String tCode){
String seatName = null;
switch(tCode){
case "TA" : seatName = "특실" ; break;
case "TB" : seatName = "1등칸" ; break;
case "TC" : seatName = "보통칸"; break;
}
return seatName;
}
private String getKindName(String ppCode){
String kindName = null;
switch(ppCode){
case "P0" : kindName = "일반" ; break;
case "P1" : kindName = "소인" ; break;
case "P2" : kindName = "군인"; break;
case "P3" : kindName = "장애인"; break;
}
return kindName;
}
private double getRate(String ppCode){
double rate = 0.0;
switch(ppCode){
case "P0" : rate = 0.0 ; break;
case "P1" : rate = 0.5 ; break;
case "P2" : rate = 0.3 ; break;
case "P3" : rate = 0.8 ; break;
}
return rate;
}
private int getDanga(String tName, String seatName){
int danga = 0;
switch(tName){
case "새마을호" : danga = (seatName.equals("특실"))? 80 :
(seatName.equals("1등칸")) ? 65 : 50; break;
case "무궁화호" : danga = (seatName.equals("특실"))? 60 :
(seatName.equals("1등칸")) ? 55 : 40; break;
case "통일호" : danga = 30; break;
}
return danga;
}
}
public class Customer {
private int id;
private String tscode; //열차코드
private String pcode; //장소코드
private String jumin1; //주민번호1
private String jumin2; //주민번호2
private String ppcode; //할증코드
private String region; //장소명
private String gender; //성별
private String tname; //열차명
private String sname; //좌석명
private String kind; //할증종류
private int price; //할인액
private int charge; //차비
public Customer(){}
public Customer(String tscode, String pcode, String jumin1,String jumin2, String ppcode) {
this.tscode = tscode;
this.pcode = pcode;
this.jumin1 = jumin1;
this.jumin2 = jumin2;
this.ppcode = ppcode;
}
@Override
public String toString(){
return String.format("%2d%10s%7s%10s%10s%10s%,15d%,15d\n",
this.id, this.region, this.gender, this.tname,
this.sname,this.kind, this.price,this.charge);
}
public String getTscode() {
return tscode;
}
public void setTscode(String tscode) {
this.tscode = tscode;
}
public String getPcode() {
return pcode;
}
public void setPcode(String pcode) {
this.pcode = pcode;
}
public String getJumin1() {
return jumin1;
}
public void setJumin1(String jumin1) {
this.jumin1 = jumin1;
}
public String getJumin2() {
return jumin2;
}
public void setJumin2(String jumin2) {
this.jumin2 = jumin2;
}
public String getPpcode() {
return ppcode;
}
public void setPpcode(String ppcode) {
this.ppcode = ppcode;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getTname() {
return tname;
}
public void setTname(String tname) {
this.tname = tname;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getCharge() {
return charge;
}
public void setCharge(int charge) {
this.charge = charge;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class CustomerController implements ActionListener {
private JPanel panel;
private JTextField tfTCode, tfPCode, tfJumin1, tfJumin2, tfPpCode;
private Vector<Customer> vector;
private int count;
public CustomerController(JPanel panel, Vector<Customer> vector,
JTextField tfTCode, JTextField tfPCode,
JTextField tfJumin1, JTextField tfJumin2, JTextField tfPpCode){
this.panel = panel; this.vector = vector;
this.tfTCode = tfTCode; this.tfPCode = tfPCode;
this.tfJumin1 = tfJumin1; this.tfJumin2 = tfJumin2; this.tfPpCode = tfPpCode;
}
@Override
public void actionPerformed(ActionEvent e) {
Customer customer = customerAdd();
customerCalc(customer);
customer.setId(++count);
this.vector.addElement(customer);
JOptionPane.showMessageDialog(this.panel, "1 Register Success!!!", "메시지",
JOptionPane.INFORMATION_MESSAGE);
}
private Customer customerAdd(){
Customer customer = new Customer(this.tfTCode.getText().trim(), this.tfPCode.getText().trim(),
this.tfJumin1.getText().trim(), this.tfJumin2.getText().trim(),
this.tfPpCode.getText().trim());
this.tfTCode.setText(""); this.tfPCode.setText("");
this.tfJumin1.setText(""); this.tfJumin2.setText("");
this.tfPpCode.setText("");
return customer;
}
private void customerCalc(Customer customer){
Calc calc = new Calc(customer);
calc.calc();
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.SQLException;
import java.util.Vector;
import javax.swing.JPanel;
import javax.swing.JTable;
public class DisplayController implements ActionListener {
private JTable table1, table2, table3, table4;
private Vector<Customer> vector;
public DisplayController(Vector<Customer> vector, JTable table1, JTable table2, JTable table3, JTable table4){
this.vector = vector;
this.table1 = table1;
this.table2 = table2;
this.table3 = table3;
this.table4 = table4;
}
@Override
public void actionPerformed(ActionEvent e) {
this.table1.setModel(
new MyTableModel1(Utility.getRegionCustomer(this.vector, "서울")));
this.table2.setModel(
new MyTableModel1(Utility.getRegionCustomer(this.vector, "부산")));
this.table3.setModel(
new MyTableModel1(Utility.getRegionCustomer(this.vector, "대구")));
this.table4.setModel(
new MyTableModel1(Utility.getRegionCustomer(this.vector, "광주")));
}
}
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.BevelBorder;
import javax.swing.border.TitledBorder;
public class InputPanel extends JPanel {
private JButton btnRegister;
private JTextField tfTCode, tfPCode, tfJumin1, tfJumin2, tfPpCode;
private JLabel labelTCode, labelPCode, labelJumin, labelPpCode;
private Font font;
private Vector<Customer> vector;
public InputPanel(Vector<Customer> vector){
this.vector = vector;
this.font = new Font("Monospace", Font.BOLD, 20);
this.setLayout(new FlowLayout());
this.add(this.getPanel());
}
private JPanel getPanel(){
JPanel p = new JPanel();
p.setLayout(new BorderLayout());
p.setBorder(new TitledBorder(
new BevelBorder(BevelBorder.RAISED), "열차예매 정보 입력"));
p.add("South", this.getSouthPanel());
p.add("West", this.getWestPanel());
p.add("Center", this.getCenterPanel());
CustomerController controller = new CustomerController(this,this.vector, this.tfTCode, this.tfPCode,
this.tfJumin1, this.tfJumin2, this.tfPpCode);
this.btnRegister.addActionListener(controller);
return p;
}
private JPanel getCenterPanel(){
JPanel p = new JPanel();
p.setLayout(new GridLayout(4,1,10,10));
p.add(this.tfTCode = new JTextField(15));
tfTCode.setFont(this.font);
p.add(this.tfPCode = new JTextField(15));
tfPCode.setFont(this.font);
p.add(this.tfJumin1 = new JTextField(7));
tfJumin1.setFont(this.font);
p.add(this.tfJumin2 = new JTextField(8));
tfJumin2.setFont(this.font);
JPanel p1 = new JPanel();
JLabel labelDash = new JLabel("-");
labelDash.setFont(this.font);
p1.add(this.tfJumin1); p1.add(labelDash); p1.add(this.tfJumin2); //위에있는 것을 다시 정의하면 그 공간이 사라지고 새로운 공간을 넣음.
p.add(p1);
p.add(this.tfPpCode = new JTextField(15));
tfPpCode.setFont(this.font);
return p;
}
private JPanel getWestPanel(){
JPanel p = new JPanel();
p.setLayout(new GridLayout(4,1,10,10));
p.add(this.labelTCode = new JLabel("열차 좌석 코드 : ", JLabel.RIGHT));
this.labelTCode.setFont(this.font);
p.add(this.labelPCode = new JLabel("장소 코드 : ", JLabel.RIGHT));
this.labelPCode.setFont(this.font);
p.add(this.labelJumin = new JLabel("주민등록번호 : ", JLabel.RIGHT));
this.labelJumin.setFont(this.font);
p.add(this.labelPpCode = new JLabel("할증 코드 : ", JLabel.RIGHT));
this.labelPpCode.setFont(this.font);
return p;
}
private JPanel getSouthPanel(){
JPanel p = new JPanel();
p.add(btnRegister = new JButton(" 예약하기 "));
this.btnRegister.setFont(this.font);
this.btnRegister.setBorder(new BevelBorder(BevelBorder.RAISED));
return p;
}
}
import java.awt.Container;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;
public class Main {
private JFrame f;
private JTabbedPane pane;
private Container con;
private Vector<Customer> vector;
private void display(){
f = new JFrame("열차예매관리프로그램");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
con = f.getContentPane();
pane = new JTabbedPane();
this.vector = new Vector<Customer>(1,1);
pane.add(new InputPanel(this.vector), "데이터입력");
pane.add(new OutputPanel(this.vector), "데이터출력");
con.add(pane, "Center");
f.setSize(700,900);
f.setVisible(true);
}
public static void main(String[] args) {
new Main().display();
}
}
import java.util.Vector;
import javax.swing.table.DefaultTableModel;
public class MyTableModel1 extends DefaultTableModel{
private Vector<Customer> vector; //서울고객명단
public MyTableModel1(Vector<Customer> vector){
this.vector = vector;
dataAddToTable();
}
private void dataAddToTable(){
String [] columnArray = {"번호", "지역", "성별", "열차명", "좌석", "할증종류", "할인액", "차비"};
Vector<String> colVector = new Vector<String>(1,1);
for(String str : columnArray) colVector.addElement(str);
Vector<Object> dataVector = new Vector<Object>(1,1);
for(int i = 0 ; i < this.vector.size(); i++){
Customer customer = this.vector.get(i);
Vector<String> row = new Vector<String>(1,1);
row.addElement(String.valueOf(customer.getId()));
row.addElement(customer.getRegion());
row.addElement(customer.getGender());
row.addElement(customer.getTname());
row.addElement(customer.getSname());
row.addElement(customer.getKind());
row.addElement(String.valueOf(customer.getPrice()));
row.addElement(String.valueOf(customer.getCharge()));
dataVector.addElement(row);
}
this.setDataVector(dataVector, colVector);
}
}
import java.util.Vector;
import javax.swing.table.DefaultTableModel;
public class MyTableModel2 extends DefaultTableModel{
private Vector<Customer> vector; //부산고객명단
public MyTableModel2(Vector<Customer> vector){
this.vector = vector;
dataAddToTable();
}
private void dataAddToTable(){
String [] columnArray = {"번호", "지역", "성별", "열차명", "좌석", "할증종류", "할인액", "차비"};
Vector<String> colVector = new Vector<String>(1,1);
for(String str : columnArray) colVector.addElement(str);
Vector<Object> dataVector = new Vector<Object>(1,1);
for(int i = 0 ; i < this.vector.size(); i++){
Customer customer = this.vector.get(i);
Vector<String> row = new Vector<String>(1,1);
row.addElement(String.valueOf(customer.getId()));
row.addElement(customer.getRegion());
row.addElement(customer.getGender());
row.addElement(customer.getTname());
row.addElement(customer.getSname());
row.addElement(customer.getKind());
row.addElement(String.valueOf(customer.getPrice()));
row.addElement(String.valueOf(customer.getCharge()));
dataVector.addElement(row);
}
this.setDataVector(dataVector, colVector);
}
}
import java.util.Vector;
import javax.swing.table.DefaultTableModel;
public class MyTableModel3 extends DefaultTableModel{
private Vector<Customer> vector; //대구고객명단
public MyTableModel3(Vector<Customer> vector){
this.vector = vector;
dataAddToTable();
}
private void dataAddToTable(){
String [] columnArray = {"번호", "지역", "성별", "열차명", "좌석", "할증종류", "할인액", "차비"};
Vector<String> colVector = new Vector<String>(1,1);
for(String str : columnArray) colVector.addElement(str);
Vector<Object> dataVector = new Vector<Object>(1,1);
for(int i = 0 ; i < this.vector.size(); i++){
Customer customer = this.vector.get(i);
Vector<String> row = new Vector<String>(1,1);
row.addElement(String.valueOf(customer.getId()));
row.addElement(customer.getRegion());
row.addElement(customer.getGender());
row.addElement(customer.getTname());
row.addElement(customer.getSname());
row.addElement(customer.getKind());
row.addElement(String.valueOf(customer.getPrice()));
row.addElement(String.valueOf(customer.getCharge()));
dataVector.addElement(row);
}
this.setDataVector(dataVector, colVector);
}
}
import java.util.Vector;
import javax.swing.table.DefaultTableModel;
public class MyTableModel4 extends DefaultTableModel{
private Vector<Customer> vector; //광주고객명단
public MyTableModel4(Vector<Customer> vector){
this.vector = vector;
dataAddToTable();
}
private void dataAddToTable(){
String [] columnArray = {"번호", "지역", "성별", "열차명", "좌석", "할증종류", "할인액", "차비"};
Vector<String> colVector = new Vector<String>(1,1);
for(String str : columnArray) colVector.addElement(str);
Vector<Object> dataVector = new Vector<Object>(1,1);
for(int i = 0 ; i < this.vector.size(); i++){
Customer customer = this.vector.get(i);
Vector<String> row = new Vector<String>(1,1);
row.addElement(String.valueOf(customer.getId()));
row.addElement(customer.getRegion());
row.addElement(customer.getGender());
row.addElement(customer.getTname());
row.addElement(customer.getSname());
row.addElement(customer.getKind());
row.addElement(String.valueOf(customer.getPrice()));
row.addElement(String.valueOf(customer.getCharge()));
dataVector.addElement(row);
}
this.setDataVector(dataVector, colVector);
}
}
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class OutputPanel extends JPanel {
private JButton btnDisplay, btnSave;
private JTable table1, table2, table3, table4;
private JScrollPane pane1, pane2, pane3, pane4;
private Vector<Customer> vector;
private Font font;
public OutputPanel(Vector<Customer> vector){
this.vector = vector;
this.setLayout(new BorderLayout());
this.font = new Font("Monospace", Font.BOLD, 15);
this.add("North", this.getNorthPanel());
this.add("Center", this.getCenterPanel());
btnDisplay.addActionListener(new DisplayController(this.vector, table1, table2, table3, table4));
btnSave.addActionListener(new SaveAction(this, this.vector));
}
private JPanel getNorthPanel(){
JPanel p = new JPanel();
p.add(this.btnDisplay = new JButton("Display"));
p.add(this.btnSave = new JButton("Backup"));
return p;
}
private JPanel getCenterPanel(){
JPanel p = new JPanel();
p.setLayout(new GridLayout(4,1,10,0));
this.table1 = new JTable();
this.table1.setRowHeight(25);
this.table1.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
this.table1.setFont(this.font);
this.pane1 = new JScrollPane(this.table1);
this.table2 = new JTable();
this.table2.setRowHeight(25);
this.table2.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
this.table2.setFont(font);
this.pane2 = new JScrollPane(this.table2);
this.table3 = new JTable();
this.table3.setRowHeight(25);
this.table3.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
this.table3.setFont(this.font);
this.pane3 = new JScrollPane(this.table3);
this.table4 = new JTable();
this.table4.setRowHeight(25);
this.table4.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
this.table4.setFont(this.font);
this.pane4 = new JScrollPane(this.table4);
p.add(pane1);
p.add(pane2);
p.add(pane3);
p.add(pane4);
return p;
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.Vector;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class SaveAction implements ActionListener {
private JPanel panel;
private Vector<Customer> vector;
public SaveAction(JPanel panel, Vector<Customer> vector){
this.panel = panel;
this.vector = vector;
}
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser jc = new JFileChooser(".");
int choice = jc.showSaveDialog(this.panel);
if(choice == JFileChooser.CANCEL_OPTION) return;
java.io.File file = jc.getSelectedFile();
BufferedWriter bw = null;
try{
bw = new BufferedWriter(new FileWriter(file));
printLabel(bw);
if(this.vector.size() == 0){
JOptionPane.showMessageDialog(this.panel, "데이터가 없습니다", "Warning",
JOptionPane.WARNING_MESSAGE);
return;
}
for(int i = 0 ; i < this.vector.size() ; i++){
Customer customer = vector.get(i);
bw.write(customer.toString());
bw.flush();
}
JOptionPane.showMessageDialog(this.panel, file.getAbsolutePath() + "에 잘 저장됐습니다.");
}catch(IOException ex){
JOptionPane.showMessageDialog(this.panel, ex.getMessage(), "Error",
JOptionPane.ERROR_MESSAGE);
}finally{
try{
bw.close();
}catch(IOException ex){}
}
}
private void printLabel(BufferedWriter bw) throws IOException {
bw.write(" <<금일 지역별 열차 예약 현황>>\n");
bw.write("--------------------------------------------------------------------------------\n");
bw.write("번호 지역 성별 열차명 좌석 할증종류 할인액 차비\n");
bw.write("--------------------------------------------------------------------------------\n");
}
}
import java.util.Vector;
public class Utility {
public static Vector<Customer> getRegionCustomer(Vector<Customer> original, String region){
Vector<Customer> temp = new Vector<Customer>(1,1);
for(int i = 0 ; i < original.size() ; i++){
Customer customer = original.get(i);
if(customer.getRegion().equals(region))
temp.addElement(customer);
}
return temp;
}
}
'Java & Oracle' 카테고리의 다른 글
File, 탐색기, 직렬화, java.net( InetAddress), Vmware Workstation으로 윈도우 깔기(한글 적용, Ubuntu 한글 적용) (0) | 2014.04.01 |
---|---|
자바 I/O (RandomAccess까지) (0) | 2014.03.31 |
자바 성적프로그램v2.0, 환자관리프로그램, JavaSoft회사 프로그램 (0) | 2014.03.27 |
자바 image 올리기, Swing, TabbedPane, swing을 이용한 성적관리프로그램 (0) | 2014.03.26 |
이클립스UML설치, GUI : Frame, Layout, Panel, EventType 4가지 (0) | 2014.03.25 |