JAVA
JAVA 7주차
Zㅣ존수빈zz
2022. 12. 15. 17:20
1. Synchronized (동기화)
- 하나의 클래스를 두 쓰레드가 사용할 때 synchronized를 사용하여 하나의 변수를 공유하도록 한다.
// 동기화 하지 않았을 경우 - 서로 다른 쓰레드가 변수를 각자 따로 사용
public class Sync1 {
public static void main(String[] args) {
MyTicket myTicket = new MyTicket();
Thread t1 = new Thread(myTicket);
Thread t2 = new Thread(myTicket);
t1.start();
t2.start();
}
}
class MyTicket implements Runnable {
private int ticket = 10;
@Override
public void run() {
for(int i=0; i<10; i++) {
try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}
sellTicket();
}
}
public void sellTicket() {
ticket -= 1;
if(ticket <= 0) {
System.out.println("좌석이 남아있지 않습니다.");
return;
}
System.out.println("현재 좌석은 "+ticket+"개 남았습니다.");
}
}
// 결과:
//현재 좌석은 8개 남았습니다.
//현재 좌석은 8개 남았습니다.
//현재 좌석은 7개 남았습니다.
//현재 좌석은 7개 남았습니다.
//현재 좌석은 6개 남았습니다.
//현재 좌석은 6개 남았습니다.
//현재 좌석은 4개 남았습니다.
//현재 좌석은 4개 남았습니다.
//현재 좌석은 3개 남았습니다.
//현재 좌석은 3개 남았습니다.
//현재 좌석은 2개 남았습니다.
//현재 좌석은 2개 남았습니다.
//좌석이 남아있지 않습니다.
//현재 좌석은 0개 남았습니다.
//좌석이 남아있지 않습니다.
//좌석이 남아있지 않습니다.
// 동기화했을 경우 - 서로 다른 쓰레드 객체가 하나의 변수를 공유
package Day12;
public class Sync1 {
public static void main(String[] args) {
MyTicket myTicket = new MyTicket();
Thread t1 = new Thread(myTicket);
Thread t2 = new Thread(myTicket);
t1.start();
t2.start();
}
}
class MyTicket implements Runnable {
private int ticket = 10;
@Override
public void run() {
for(int i=0; i<10; i++) {
try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}
sellTicket();
}
}
public synchronized void sellTicket() { // 동기화된 함수: 변수를 사용할 때 중첩되지 않는다.
ticket -= 1;
// 티켓 판매 후 남은 좌석 체크
if(ticket <= 0) {
System.out.println("좌석이 남아있지 않습니다.");
return;
}
System.out.println("현재 좌석은 "+ticket+"개 남았습니다.");
}
}
// 결과
//현재 좌석은 8개 남았습니다.
//현재 좌석은 7개 남았습니다.
//현재 좌석은 6개 남았습니다.
//현재 좌석은 5개 남았습니다.
//현재 좌석은 4개 남았습니다.
//현재 좌석은 3개 남았습니다.
//현재 좌석은 2개 남았습니다.
//현재 좌석은 1개 남았습니다.
//좌석이 남아있지 않습니다.
//좌석이 남아있지 않습니다.
2. Stream
- 파일 검색, 읽기, 만들기, 삭제하기
- C드라이브의 모든 파일 혹은 폴더를 배열로 저장하여 출력하기
public class Stream1 {
public static void main(String[] args) {
FileFound ff = new FileFound();
ff.go("c:\\");
}
}
class FileFound {
public void go(String path) {
System.out.println(path+"안에 있는 파일 검색");
File file = new File(path); // File 클래스에 경로를 넘겨줌
String file_list[] = file.list(); // 모든 파일 목록 배열로 저장
// 가져온 파일 목록을 반복문을 통해 하나씩 보여주기
for(int i=0; i<file_list.length; i++) {
System.out.println((i+1)+". "+file_list[i]);
}
// 빠른 for문 - python형태의 for문으로 배열길이가 정해져있고 의도가 명확할 때 사용할 수 있다.
for(String str : file_list) {
if(str.contains(".")){
System.out.println("폴더명: "+ str);
}else {
System.out.println("파일명: "+str);
}
}
}
}
- 지정한 위치에 파일 만들고 삭제하기
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class Stream2 {
public static void main(String[] args) {
FileCtrl fc = new FileCtrl();
int result = fc.delFile("C:\\java");
// fc.makeFile("C:\\java");
System.out.println(result);
}
}
class FileCtrl {
// 파일 만들기
public int makeFile(String path) { // 생성에 실패하면 0, 성공하면 1을 반환
int isSuccess = 0;
Scanner sc = new Scanner(System.in);
System.out.println("생성할 파일 이름을 입력하세요(확장자까지)>>");
String filename = sc.nextLine();
File file = new File(path + "\\" + filename);
if(file.exists()) {
System.out.println("이미 존재하는 파일입니다.");
return -1;
}
try {
file.createNewFile();
isSuccess = 1;
} catch (IOException e) {
isSuccess = 0;
e.printStackTrace();
} finally {
sc.close();
}
if(file.exists()) {
System.out.println("파일 생성 완료!");
}
return isSuccess;
}
// 파일 삭제하기
public int delFile(String path) {
Scanner sc = new Scanner(System.in);
System.out.println("삭제할 파일 이름을 입력하세요(확장자까지)>>");
String filename = sc.nextLine();
File file = new File(path + "\\" + filename);
boolean isDeleted = file.delete();
if(isDeleted) {
System.out.println("삭제 성공!");
return 1;
}else {
System.out.println("삭제 실패...");
return 0;
}
}
}
- 파일에 내용입력하고 읽어오기
파일은 '바이트'단위로 적기 때문에 문자열을 바이트로 바꿔주는 절차를 거쳐야 한다
- FileOutputStream: byte 단위로 파일을 내보내는 메서드
- InputStream: byte단위의 파일을 다시 문자열로 받아오는 메서드
- InputStreamReader: 문자열 형식을 UTF-8로 변환하기 위하여 사용
- BufferedFeader: 문자열로 바꾸기 위해 버퍼단위로 읽음
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public class Stream3 {
public static void main(String[] args) {
MyFileIO fio = new MyFileIO();
fio.putText("C:\\java\\test.txt");
fio.readText("C:\\java\\test.txt");
}
}
class MyFileIO {
// 파일에 내용 입력하기(OutputStream)
public void putText(String file) {
FileOutputStream fout = null; // byte단위로 내보내는 메서드
Scanner sc = null;
try {
fout = new FileOutputStream(file, true); // true가 없으면 기존의 내용 삭제 후 입력(덮어씀)
sc = new Scanner(System.in);
System.out.print("입력할 내용>>");
String msg = sc.nextLine()+" \n";
// 문자열을 바이트로 바꾸기
byte[] byteArray = msg.getBytes();
fout.write(byteArray);
System.out.println("입력완료");
} catch (Exception e) {
e.printStackTrace();
System.out.println("입력실패...");
} finally {
try {
fout.close();
sc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 파일 읽어오기(InputStream)
public void readText(String file) {
FileInputStream fin = null;
try {
fin = new FileInputStream(file); // 파일을 불러온다
// UTF-8로 변환한다
InputStreamReader isr = new InputStreamReader(fin, "UTF-8");
BufferedReader br = new BufferedReader(isr);
String msg = null;
while((msg = br.readLine()) != null) {
System.out.println(msg);
}
} catch(Exception e) {
e.printStackTrace();
System.out.println("파일 읽기 실패...");
} finally {
try {
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3. socket
- 프로그램 간 메시지 주고받기
- 소켓통신을 하려면 같은 네트워크를 사용해야 한다.
- ObjectInputStream: 파일이나 네트워크를 통해 전달 받은 직열화된 데이터를 다시 직렬화 하기전 객체로 만드는 것
readObject()와 함께 쓰인다.
- ObjectOutputStream : 파일이나 네트워크로 데이터를 전달하기 위해 직렬화를 수행. writeObject() 함수를 이용해서 변환
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Socket1 {
public static void main(String[] args) {
MyServer ms = new MyServer();
MyClient mc = new MyClient();
// mc.go("접속할 서버IP주소", 접속할 포트번호)
// ms.go(서버관리자가 정하는 포트번호);
}
}
// TCP / IP 통신을 Socket으로 진행
class MyServer {
// 들어오는 메시지(수신)
InputStream is;
ObjectInputStream ois;
// 나가는 메시지(송신)
OutputStream os;
ObjectOutputStream oos;
// 서버로 설정
ServerSocket serverSocket;
// 메시지를 직접적으로 처리할 소켓을 추가생성
Socket socket;
String msg;
public void go(int port) { // 서버는 컴퓨터의 IP(주소)와 설정한 PORT(대상)로 연결을 시작
try {
serverSocket = new ServerSocket(port); // client가 접속했는지 체크하는 용도
// 수신대기
while(true) {
System.out.println("수신 대기 중");
socket = serverSocket.accept(); // 누군가 들어올 때까지 대기상태
System.out.println("접속IP: "+ socket.getInetAddress());
// 누군가 접속해서 메시지를 보내면
is = socket.getInputStream();
ois = new ObjectInputStream(is);
os = socket.getOutputStream();
oos = new ObjectOutputStream(os);
// 메시지 수신 완료
msg = (String)ois.readObject();
System.out.println("클라이언트: " + msg);
String respon = "서버가 준 메시지: " + msg;
oos.writeObject(respon);
socket.close(); // 연결을 종료
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyClient {
// 들어오는 메시지(수신)
InputStream is;
ObjectInputStream ois;
// 나가는 메시지(송신)
OutputStream os;
ObjectOutputStream oos;
// 메시지를 직접적으로 처리할 소켓을 추가생성
Socket socket;
String msg;
Scanner sc = new Scanner(System.in); // 콘솔 입력을 위해(임시)
public void go(String ip, int port) {
try {
socket = new Socket(ip, port); // 서버에 접속
// 메시지를 내보낼 준비(송신준비)
os = socket.getOutputStream();
oos = new ObjectOutputStream(os);
// 메시지를 받을 준비(수신준비)
is = socket.getInputStream();
ois = new ObjectInputStream(is);
// 소켓통신
System.out.println("보낼 메시지>> ");
msg = sc.nextLine();
oos.writeObject(msg); // 메시지 송신
String respon = (String)ois.readObject();
System.out.println(respon);
socket.close(); // 소켓 연결을 끊는다
} catch (Exception e) {
e.printStackTrace();
}
}
}
4. URL
- 대표적인 통신방식
- TCP/IP: 먼저 서로 연결을 하고 메시지를 주고받음(비교적 안정적, 서버 과부하 우려, 일반적으로 많이 쓰임), Socket
- UDP: 받든 말든 상관없이 일단 보낸다(방송, 브로드캐스트, 상대의 접속여부에 관계없이 송신), 연결유지x, DatagramSocket
- HTTP: 웹 전용 통신, URL, 연결유지x
- RestAPI: HTTP통신에서 정해진 규격에 맞춰 통신하는 관례
- 웹사이트에서 Html 코드 읽어오기(네이버 영화순위)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
public class URL2 {
public static void main(String[] args) {
MyURLEx m = new MyURLEx();
m.go("https://movie.naver.com/movie/sdb/rank/rmovie.naver");
}
}
class MyURLEx {
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
URL url = null;
String str = null;
ArrayList<String> parseArray = new ArrayList<>();
public void go(String address) {
try {
url = new URL(address);
is = url.openStream();
isr = new InputStreamReader(is, "UTF-8");
br = new BufferedReader(isr);
// 버퍼리더를 문자열로 변경(한줄씩 줄바꾸면서)
while((str = br.readLine()) != null) { // str에 먼저 한줄씩 담고 null과 같은지 비교.(br.readLine(): 한줄씩 읽기)
// 내가 원하는 문자열을 찾는다
if(str.contains("<a href=\"/movie/bi/mi/basic.naver?code=") && !(str.contains("onclick"))) {
String parse = str.substring(str.indexOf("title=")+7, str.indexOf("\">")+0);
parseArray.add(parse); // 파싱한 문자열을 ArrayList에 저장
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
isr.close();
br.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
for(int i=0; i<parseArray.size();i++) {
System.out.println((i+1)+"위. "+parseArray.get(i));
}
}
}