Java 12일차 : 스레드, 동기화, 네트워크, 채팅프로그램
스레드
멀티태스킹
-
프로세스 : 운영체제에서 실행중인 하나의 프로그램
-
멀티 프로세스 : 두 개 이상의 프로세스가 실행되는 것
-
멀티 태스킹 : 두 개 이상의 프로세스를 실행하여 일을 처리하는 것
멀티스레드
-
스레드 : 프로세스 내에서 실행되는 세부 작업 단위
-
멀티 스레드 : 하나의 프로세스에서 여러 개의 스레드가 병행적으로 처리되는 것
자바에서 멀티스레드를 구현하는 방법은 2가지가 있다
- 클래스 Thread를 상속 받는 방법
- 인터페이스 runnable 을 구현하는 방법
위의 클래스 또는 인터페이스가 가진 run 메서드를 오버라이드한다. run 메서드호출은start
스레드의 생명 주기
스레드는 Thread 객체가 생성되면 생명주기를 갖게 되는데 크게 5가지로 나누게 된다.
- New – 스레드가 만들어진 상태.
- Runnable – 스레드 객체가 생성된 후에 start() 메서드를 호출하면 Runnable 상태로 이동하게 된다.
- Running – Runnable 상태에서 스레드 스케줄러에 의해 Running 상태로 이동하게 된다.
- Blocked – 스레드가 다른 특정한 이유로 Running 상태에서 Blocked 상태로 이동하게 된다.
- Dead – 스레드가 종료되면 그 스레드는 다시 시작할 수 없게 된다.
반환형 | 메서드 | 설명 |
---|---|---|
static void | sleep(long mills) | mills에 지정된 시간만큼 대기 |
String | getName() | 스레드의 이름 반환 |
void | setName(String name) | 스레드 이름 지정 |
void | start() | 스레드 시작 |
int | getPriority() | 스레드의 우선순위 반환 |
void | setPriority(int p) | 스레드의 우선순위 지정 |
void | join() | join()메서드를 호출한 스레드가 종료시까지 현재 스레드 대기 |
static void | yield() | 수행중인 스레드 중 우선순위가 같은 다른 스레드에게 제어권 넘김 |
static Thread | currentThread() | 현 수행되는 스레드 객체 리턴 |
package test.day0418;
// 스레드를 사용하지 않는 예(하나의 스레드)
public class ThreadEx1 {
String name;
int num;
public ThreadEx1(String name, int num) {
this.name = name;
this.num = num;
}
public void run() {
for(int i=1 ; i <= num ; i++) {
System.out.println(name + " => " + i);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ThreadEx1 th1 = new ThreadEx1("one", 300);
ThreadEx1 th2 = new ThreadEx1("two", 300);
ThreadEx1 th3 = new ThreadEx1("three", 300);
//run메서드 호출
th1.run();
th2.run();
th3.run();
}
}
package test.day0418;
//ex1번을 복사하여 스레드를 상속받는 클래스로 만들자
public class ThreadEx2 extends Thread {
String name;
int num;
public ThreadEx2(String name, int num) {
this.name = name;
this.num = num;
}
//스레드 상속받을 시 이건 오버라이드 메서드가 됨
@Override
public void run() {
for(int i=1 ; i <= num ; i++) {
System.out.println(name + " => " + i);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ThreadEx2 th1 = new ThreadEx2("one", 300);
ThreadEx2 th2 = new ThreadEx2("two", 300);
ThreadEx2 th3 = new ThreadEx2("three", 300);
//스레드의 run호출은 start이다.
th1.start(); //runnable 상태에서 스케줄러에 의해 하나씩 running 상태가 된다.
th2.start();
th3.start();
}
}
package test.day0418;
//ex2를 Runnable로 상속받는(구현하는) 클래스로 구현해보자
public class ThreadEx3 implements Runnable {
String name;
int num;
public ThreadEx3(String name, int num) {
this.name = name;
this.num = num;
}
//스레드 상속받을 시 이건 오버라이드 메서드가 됨
@Override
public void run() {
for(int i=1 ; i <= num ; i++) {
System.out.println(name + " => " + i);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//runnable 인터페이스를 구현한 클래스를 생성한것에 불과
ThreadEx3 ex1 = new ThreadEx3("one", 300);
ThreadEx3 ex2 = new ThreadEx3("two", 300);
ThreadEx3 ex3 = new ThreadEx3("three", 300);
//runnable로 구현할 경우에는 쓰레드를 생성해줘야 한다.
Thread th1 = new Thread(ex1);
Thread th2 = new Thread(ex2);
Thread th3 = new Thread(ex3);
//스레드의 run호출은 start이다.
th1.start(); //runnable 상태에서 스케줄러에 의해 하나씩 running 상태가 된다.
th2.start();
th3.start();
}
}
동기화
-
여러 스레드가 동시에 특정 메소드에 접근해서 처리하다보면 문제가 발생할 수 있다.
-
이 때 특정 스레드가 해당 메서드를 다 처리하기 전까지는 다른 스레드는 기다려야하며 처리가 끝날때까지 접근을 못하도록 하려면 이렇게..
public synchronized void hello(){
}
네트워크
TCP
- Transmission Control Protocol
- 신뢰할 수 있는 프로토콜로서 , 데이터를 상대측까지 제대로 전달했는지 확인 메시지를 주고 받음으로써 데이터의 송수신 상태를 점검한다
UDP
- User Datagram Protocol
- 신뢰할 수 없는 프로토콜로서, 데이터를 보내기만 하고 확인 메시지를 주고 받지 않기 때문에 제대로 전달했는지 확인하지 않는다.
- TCP가 전화라면 UDP는 편지같은 개념
InetAddress
- InetAddress 클래스는 IP 주소를 표현한 클래스이다.
- 자바에서는 모든 IP 주소를 InetAddress 클래스를 사용한다.
package test.day0418;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class InetAddressEx5 {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
InetAddress myAddr = InetAddress.getLocalHost();
System.out.println("local ip: " + myAddr.getHostAddress());
System.out.println("local name: " + myAddr.getHostName());
}catch(UnknownHostException e) {
e.printStackTrace();
}
//String hostName = "www.naver.com";
String hostName = "www.google.com";
try {
InetAddress addr[] = InetAddress.getAllByName(hostName);
for(InetAddress ia:addr) {
System.out.println("name: " + ia.getHostName());
System.out.println("ip: " + ia.getHostAddress());
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package test.day0418;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
//네이버의 소스 읽어오기
public class URLEx6 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String hostName = "http://www.google.com";
try {
URL url = new URL(hostName);
InputStream is = url.openStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while(true) {
String line = br.readLine();
if(line == null)
break;
System.out.println(line);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
ServerSocket
- 서버에서 접속하는 클라이언트를 허용하기 위한 클래스
- 허용을 하게되면 양방향 통신을 할수 있는 Socket이 생성된다
- 자바프로그램은 소켓이라는 개념을 통해서 네트워크 통신을 한다
package test.day0418;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerSocketEx7 extends Thread {
ServerSocket server;
public ServerSocketEx7() {
try {
server = new ServerSocket(7000);
System.out.println("server socket successful");
} catch (IOException e) {
System.out.println("서버소켓 생성실패 ");
}
}
@Override
public void run() {
while(true) {
try {
Socket socket = server.accept();
InetAddress inet = socket.getInetAddress();
System.out.println("접속한 컴퓨터 이름: " + inet.getHostName());
System.out.println("접속한 컴퓨터의 ip: " + inet.getHostAddress());
System.out.println("--------------------------------------");
} catch (IOException e) {
System.out.println("클라이언트 서버에 접속실패 " +e.getMessage());
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ServerSocketEx7 ss = new ServerSocketEx7();
ss.start(); //run method호출
}
}
package test.day0418;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
public class ClientSocketEx7 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Socket socket = null;
Scanner sc = new Scanner(System.in);
String lastip;
System.out.println("접속할 서버의 마지막 ip숫자를 입력하세요.");
lastip = sc.nextLine();
String serverip = "192.168.0." + lastip;
try {
socket = new Socket(serverip, 7000);
System.out.println("서버 접속 성공");
} catch (IOException e) {
System.out.println("서버 접속 실패 ");
}
}
}
채팅 프로그램 만들기
package test.day0418;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;
public class ServerSocketEx8 extends Thread {
ServerSocket server;
Vector<ConnectClient> list;
public ServerSocketEx8() {
try {
server = new ServerSocket(7000);
System.out.println("server socket successful");
//클라이언트 정보를 담을 벡터 생성
list = new Vector<ConnectClient>();
} catch (IOException e) {
System.out.println("서버소켓 생성실패 ");
}
}
@Override
public void run() {
while(true) {
try {
Socket socket = server.accept();
InetAddress inet = socket.getInetAddress();
System.out.println("접속한 컴퓨터 이름: " + inet.getHostName());
System.out.println("접속한 컴퓨터의 ip: " + inet.getHostAddress());
System.out.println("--------------------------------------");
//접속한 클라이언트를 생성 후 벡터에 담아서 서버가 가지고 있어야만 한다.
ConnectClient cc = new ConnectClient(socket);
list.add(cc);
cc.start();//내부클래스의 run메서드 호출
} catch (IOException e) {
System.out.println("클라이언트 서버에 접속실패 " +e.getMessage());
}
}
}
class ConnectClient extends Thread{
Socket socket;
BufferedReader br;
PrintWriter pw;
public ConnectClient(Socket socket) {
this.socket = socket;
//io클래스 생성
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
while(true) {
//클라이언트가 보내는 메세지 읽기
try {
String msg = br.readLine();
System.out.println(msg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//클라이언트와 대화를 할 내부클래스 - 스레드여야 한다.
public static void main(String[] args) {
// TODO Auto-generated method stub
ServerSocketEx8 ss = new ServerSocketEx8();
ss.start(); //run method호출
}
}
package test.day0418;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class ClientSocketEx8 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Socket socket = null;
Scanner sc = new Scanner(System.in);
String lastip;
BufferedReader br = null;
PrintWriter pw = null;
System.out.println("접속할 서버의 마지막 ip숫자를 입력하세요.");
lastip = sc.nextLine();
String serverip = "192.168.0." + lastip;
try {
socket = new Socket(serverip, 7000);
System.out.println("서버 접속 성공");
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while(true) {
System.out.println("메세지입력 ");
String msg = sc.nextLine();
if(msg.equalsIgnoreCase("q"))
break;
pw.write(msg + "\n");
pw.flush();
}
} catch (IOException e) {
System.out.println("서버 접속 실패 ");
}
}
}
Comments