학원 - Thread / Stream
1. Thread
- 스레드: 프로그램 내에서 실행되는 작업 단위
- Thread 클래스를 상속받거나 Runnable 인터페이스를 구현하여 스레드 구현 가능
- Thread 클래스를 상속받으면 단일상속의 특성으로 다른 클래스를 상속받지 못하기 때문에
Runnable 인터페이스를 구현하는 방법을 주로 사용
- 스레드를 통해 두가지의 이상의 작업을 동시에 진행할 수 있음
(실제로 동시에 처리되는 것은 아니고 번갈아가며 처리)
- 스레드 클래스에서 run()
메서드를 오버라이딩하여 실행할 코드 작성, start();
로 실행
- 스레드의 동기화: 하나의스레드가 작업을 완료할 때까지 나머지 스레드는 대기하도록 함
메서드의 반환타입 앞에 synchronized를 붙여주거나 synchronized (객체의 참조변수)
블럭 안에 코드를 작성함
- Thread.sleep(millis)
: 해당 객체를 millisecond 동안 잠들게(일시정지) 하고 주어진 시간이 지나면 다시 실행
- JFrame을 활용하여 Thread 구현 연습 - 키를 입력하면 bar 게이지 증가, 입력이 없으면 게이지 감소
public class TabAndThreadEx extends JFrame {
Container c = getContentPane();
MyLabel bar = new MyLabel();
KeyAdapter adapter = new KeyAdapter() {
public void keyPressed(KeyEvent e) {
bar.fill();
};
};
int barSize = 150;
ConsumeThread th = new ConsumeThread();
public TabAndThreadEx() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("아무 키나 빨리 눌러 바 채우기");
setSize(350, 200);
c.setLayout(null);
bar.setBounds(20, 50, 300, 20);
bar.setOpaque(true);
c.add(bar);
c.addKeyListener(adapter);
c.setFocusable(true);
c.requestFocus();
th.start();
setVisible(true);
}
public class MyLabel extends JLabel {
public MyLabel() {
setBackground(Color.ORANGE);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.MAGENTA);
g.fillRect(0, 0, barSize, 20);
}
public synchronized void fill() {
System.out.println("fill, barSize: " + barSize);
if (barSize == 300) return;
barSize++;
repaint();
notify();
}
public synchronized void consume() {
System.out.println("consume, barSize: " + barSize);
if (barSize == 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
barSize--;
repaint();
}
}
public class ConsumeThread extends Thread {
public void run() {
while (true) {
try {
Thread.sleep(100);
bar.consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
new TabAndThreadEx();
}
}
2. Stream
- 스트림: 다양한 데이터를 표준화된 방법으로 처리하는 방식을 메서드로 정의해놓은 것
- 처리할 데이터의 종류에 따라 파일 읽고 쓰기를 할 객체가 다름
- 읽기/쓰기는 모두 프로그램을 기준으로 생각해야 함
- File 객체 이해하기
public class FileClassExample {
public static void main(String[] args) {
File f1 = new File("C:/Windows/system.ini"); // 파일 객체. 실제 파일이 아님
String name = f1.getName();
System.out.println("name: " + name); // name: system.ini
String path = f1.getPath();
System.out.println("path: " + path); // path: C:\Windows\system.ini
String parent = f1.getParent();
System.out.println(parent); // C:\Windows
String fileOrDir = "";
if (f1.isFile())
fileOrDir = "파일";
else if (f1.isDirectory())
fileOrDir = "폴더";
System.out.println(name + "은(는) " + fileOrDir);
File f2 = new File("C:/Temp/java_sample");
/*
* String name2 = f2.getName(); String path2 = f2.getPath();
* System.out.println("f2 name: " + name2 + " / f2 path: " + path2);
* 실제로 없는 존재하지 않는 파일임 -> 생성자 파라미터값을 기준으로 값을 가져옴
*/
if (!f2.exists()) {
f2.mkdir(); // make directory
System.out.println("폴더 생성 완료");
}
File f3 = new File("C:/Temp");
File[] files = f3.listFiles();
for (File aFile : files) {
String fName = aFile.getName();
long fSize = aFile.length();
long last = aFile.lastModified();
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(last);
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
int date = cal.get(Calendar.DAY_OF_MONTH);
StringBuffer sb = new StringBuffer();
sb.append(fName);
sb.append(" | ");
sb.append(fSize + "bytes");
sb.append(" | ");
sb.append(year);
sb.append("/");
sb.append(month + 1);
sb.append("/");
sb.append(date);
System.out.println(sb.toString());
}
}
}
- FileReader, FileWriter, FileInputStream, FileOutputStream의 사용 방법 익히기
개인 학습 - 몇가지 개념 복습
- System.currentTimeMillis();
: 현재 시간을 millisecond 단위로 측정
- JTextArea에 append()
메서드가 있음(StringBuffer에만 있는 메서드가 아님)
- paintComponent
를 오버라이딩해서 그리기를 할 때, 크기나 위치 등 변화가 있으면 repaint();
를 해야 함
- sleep()
* Thread의 static 메서드
* 지정된 시간이 경과하거나 interrupted되면 깨어나서 다음 코드를 실행하는데
강제로 깨우면 throw new InterruptedException에 의해 예외를 던져, 바로 잠자는 것에서 벗어나게 됨
* try - catch를 활용한 방법이므로 catch블럭 안에는 아무 내용을 작성하지 않아도 되고
보통 delay(long millis) 등의 메서드를 만들어놓고 사용함(매번 예외처리 하기 번거로우니까)
* Thread.sleep();
을 실행하는 스레드가 잠자기를 실행함(다른 메서드 지정 불가)