Java에서 Thread를 구현하는 5-Step

 

  1. Thread 클래스를 상속받는 사용자 정의 클래스를 생성한다.
  2. Thread 클래스로부터 상속받은 public void run 메서드를 오버라이딩 한다.
  3. public void run 메서드 내에 병행처리 할 코드를 작성한다.
  4. 작성된 사용자 정의 클래스를 바탕으로 인스턴스를 생성한다.
  5. 생성된 인스턴스로부터 start() 메서드를 호출한다.
public class Exam_01 {
	public static void main(String[] args) {

//		Worker w = new Worker();
//		Worker2 w2 = new Worker2();
//		Worker3 w3 = new Worker3();
//		w.start();
//		w2.start();
//		w3.start();
		
		new Worker().start();
		new Worker2().start();
		new Worker3().start();
		
		for(int i =0; i<=99; i++) {
			System.out.print("%");
		}
		
	}
}
public class Worker extends Thread{

	public void run() {
		for(int i =0; i<=99; i++) {
			System.out.print("+");
		}
	}
}

같은 변수를 여러 스레드가 처리하도록 하는 방법

 

  • 파라미터를 넣으면 오버라이딩 안된다.
  • 설사 넣어도 콜바이밸류로 실제 값이 변하지 않음(같은이름의 다른 지역변수)
  • public static
  • 스태틱 멤버필드는 클래스 멤버필드
class PlusTarget extends Thread{
	public void run() {
		while(true) {
			Quiz_02.target++;
		}
	}
}

class MinusTarget extends Thread{
	public void run() {
		while(true) {
			Quiz_02.target--;
		}
	}
}


public class Quiz_02 {
	
	public static int target = 0;
	
	public static void main(String[] args) {
	

		
//		while(true) {
//			target++;
//		}
//		while(true) { //Unreachable code : 위의 반복문에서 벗어날수 없으므로 도달할수 없는 코드
//			target--;
//		}
		//파라미터를 넣으면 오버라이딩 안된다.설사 넣어도 콜바이밸류로 실제 값이 변하지 않음(같은이름의 다른 지역변수)
		//public static
		//스태틱 멤버필드는 클래스 멤버필드
		
		new PlusTarget().start();
		new MinusTarget().start();
		
		while(true) {
			System.out.println(target);
		}
		
	}
}

  1. static
  2. call by reference
  3. inner class 방식 , nested class 방식 : 클래스를 안에다
public class Quiz_02 {

	public static void main(String[] args) {

		int target=0;
		
//		class A{ //1.내부에 선언
//		}
		
//		Thread th = new Thread(); //2.인스턴스는 있지만 오버라이드 안되어있음

		Thread th = new Thread() { //3.Thread 클래스를 바탕으로 인스턴스를 만들건데 수정해서 만들것이다.
			int a;
		};
//		th.a // .으로 접근 못함, 자바에서 스레드형식이 a를 갖고 있다고 보지는 않음
		
		while(true) {
			System.out.println(target);
		}
	}
}

에러발생

Local variable target defined in an enclosing scope must be final or effectively final

public class Quiz_02 {
	public static void main(String[] args) {

		int target=0;

		Thread th = new Thread() { 
			
			public void run() {
				target++; //Local variable target defined in an enclosing scope must be final or effectively final
			}//지역변수 target은 상수이거나 상수와 동일한 상태여야 한다	
		};

		while(true) {
			System.out.println(target);
		}

	}
}

상수로 만들어도

The final local variable target cannot be assigned, since it is defined in an enclosing type

public class Quiz_02 {
	public static void main(String[] args) {

		final int target=0;

		Thread th = new Thread() { 
			
			public void run() {
				target++; //The final local variable target cannot be assigned, since it is defined in an enclosing type
			}
		};

		while(true) {
			System.out.println(target);
		}

	}
}

스테틱을 사용하지 않는 경우

변수는 상수가 아니면서 상수와 같이 존재하도록 멤버필드로 위치 시키기

public class Quiz_02 {
	
	public int target=0; // 스테틱 매서드 내에서는 넌스테틱을 쓰지 못함, 콜되었을 때 인스턴스 호출될지 확신 못함

	public void  func() {

		Thread th1 = new Thread() {
			public void run() {
				while(true) {
					target++;
				}
			}
		};

		Thread th2 = new Thread() {
			public void run() {
				while(true) {
					target--;
				}
			}
		};
		
		th1.start();
		th2.start();
		while(true) {
		System.out.println(target);
		}
		
	}

	public static void main(String[] args) {
		new Quiz_02().func();
	}
}

//callback 패턴
public class Quiz_02 {

	public int target=0; // 스테틱 매서드 내에서는 넌스테틱을 쓰지 못함, 콜되었을 때 인스턴스 호출될지 확신 못함

	public void  func() {

		new Thread() {
			public void run() {
				while(true) {
					target++;
				}
			}
		}.start(); //익명 inner 클래스

		new Thread() {
			public void run() {
				while(true) {
					target--;
				}
			}
		}.start();

		while(true) {
			System.out.println(target);
		}
	}
	public static void main(String[] args) {
		new Quiz_02().func();
	}
}

쌍방 채팅

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Server {

	public void  func() {
		try {
			ServerSocket server = new ServerSocket(50000);

			System.out.println("서버를 가동했습니다.");
			Socket sock = server.accept();
			System.out.println(sock.getInetAddress() + " 에서 연결"); //127.0.0.1

			DataInputStream dis = 
					new DataInputStream(sock.getInputStream());
			DataOutputStream dos = 
					new DataOutputStream(sock.getOutputStream());

			new Thread() {
				public void run() {
					try {
						while(true) {
							Scanner sc = new Scanner(System.in);
							dos.writeUTF(sc.nextLine());
							dos.flush();					
						}
					}catch(Exception e) {
						e.printStackTrace();
					}
				}
			}.start();

			new Thread() {
				public void run() {
					try {
						while(true) {
							System.out.println(sock.getInetAddress()+" : "+dis.readUTF());
						}
					}catch(Exception e) {
						e.printStackTrace();
					}
				}
			}.start();

		}catch(Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args){
		new Server().func();
	}
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {

	public void  func() {
		try {
			Socket sock  = new Socket("192.168.60.19", 50000); //127.0.0.1 //192.168.60.19
			DataInputStream dis = 
					new DataInputStream(sock.getInputStream());
			DataOutputStream dos = 
					new DataOutputStream(sock.getOutputStream());

			new Thread() {
				public void run() {
					try {
						while(true) {
							Scanner sc = new Scanner(System.in);
							dos.writeUTF(sc.nextLine());
							dos.flush();
						}
					}catch(Exception e) {
						e.printStackTrace();
					}
				}
			}.start();

			new Thread() {
				public void run() {
					try {
						while(true) {
							System.out.println(sock.getInetAddress()+" : "+dis.readUTF());
						}
					}catch(Exception e) {
						e.printStackTrace();
					}
				}
			}.start();

		}catch(Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args){
		new Client().func();
	}
}

값공유

1. 스태틱

2. call by reference

3. inner class : 코드가 짧을 때 클래스를 나누지 않고 그안에

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JOptionPane;


class WriteThread extends Thread{
	private DataOutputStream dos;
	public WriteThread(DataOutputStream dos) {
		this.dos = dos;
	}
	public void run() {
		while(true) {
			try {
				dos.writeUTF(JOptionPane.showInputDialog("메세지 입력"));
				dos.flush();
			}catch(Exception e) {
				e.printStackTrace();
				System.exit(0);
			}
		}
	}
}
class ReadThread extends Thread{
	private DataInputStream dis;
	public ReadThread(DataInputStream dis) {
		this.dis = dis;
	}
	public void run() {
		while(true) {
			try {
				System.out.println(dis.readUTF());
			}catch(Exception e) {
				e.printStackTrace();
				System.exit(0);
			}
		}
	}
}
public class Server3 {
	public static void main(String[] args) {
		try {
			ServerSocket server = new ServerSocket(20000);

			Socket sock = server.accept();
			DataInputStream dis = new DataInputStream(sock.getInputStream());
			DataOutputStream dos = new DataOutputStream(sock.getOutputStream());

			WriteThread wt = new WriteThread(dos);
			ReadThread rt = new ReadThread(dis);

			wt.start();
			rt.start();


		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;

import javax.swing.JOptionPane;

public class Client3 {
	public static void main(String[] args) {
		try {
			Socket sock = new Socket("127.0.0.1",20000);
			
			DataInputStream dis = new DataInputStream(sock.getInputStream());
			DataOutputStream dos = new DataOutputStream(sock.getOutputStream());
			
			WriteThread wt = new WriteThread(dos);
			ReadThread rt = new ReadThread(dis);
			
			wt.start();
			rt.start();
			
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}

 


다중 접속 메세지

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;


public class Server2 {
	public static void main(String[] args){
		
		try {
			ServerSocket server = new ServerSocket(20000);
			
			while(true) {
				Socket sock = server.accept();
				new SocketThread(sock).start();
			}

		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}
import java.net.Socket;

public class SocketThread extends Thread{

	private Socket sock;

	public SocketThread(Socket sock) {
		this.sock =sock;
	}

	public void run() {
		try {		
		
			System.out.println(sock.getInetAddress() + " 에서 연결");
			Thread.sleep(3000);
		}catch(Exception e){
		}
	}
}
import java.io.DataOutputStream;
import java.net.Socket;

import javax.swing.JOptionPane;

public class Client2 {
	public static void main(String[] args) {
		try {
			Socket sock  = new Socket("192.168.60.57", 20000);
			while(true) {
				DataOutputStream dos = 
						new DataOutputStream(sock.getOutputStream());
				dos.writeUTF(JOptionPane.showInputDialog("메세지 입력"));
			}	
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.HashSet;
import java.util.Set;
//다대일 서비스 프로그램
public class Server4 {
   public static void main(String[] args) throws IOException {
      
         
         ServerSocket server = new ServerSocket(50000);
         
         System.out.println("서버가 구동되었습니다.");
         System.out.println("클라이언트 연결을 대기중입니다...");

         while(true) {//여러명의 클라이이언트 받아서 쓰레드를 생성.소켓&스레드 공장
            try {
            Socket sock = server.accept();            
            new SocketThread(sock).start();   
            }catch(Exception e) {
               
            }
         }   

   }

}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.HashSet;
import java.util.Set;

public class SocketThread extends Thread{
   private Socket sock;
   DataInputStream dis;
   DataOutputStream dos;

   public SocketThread(Socket sock) {
      this.sock = sock;
   }

   public void run() {
      System.out.println(sock.getInetAddress() + "에서 연결하였습니다.");

      try {
         dis = new DataInputStream(sock.getInputStream());
      } catch (IOException e1) {

         e1.printStackTrace();
      }
      try {
         dos = new DataOutputStream(sock.getOutputStream());
      } catch (IOException e1) {

         e1.printStackTrace();
      }


      while(true) {      
         try {
            dos.writeUTF("Time/lotto/wise 중 하나를 입력해주세요");

            String msg = dis.readUTF();
            //축약하면 안됨. 그러면 if문에서 아닐때 else if 문으로 가는데 그러면 2번 이상 utf를 받아야하고 클라이언트에서는 자신의 답을 듣기 위하여 몇번을 입력해야할지 모른다.
            //if(msg.contentEquals(dis.readUTF())){
            //   }else if(msg.contentEquals(dis.readUTF())) {}
            //매우 위험

            if(msg.contentEquals("Time")) {
               SimpleDateFormat sdf = new SimpleDateFormat("yyyy"+"년 " + "MM" + "월 " + "dd" + "일 " + "HH:mm:ss");
               String strTime = sdf.format(System.currentTimeMillis());
               dos.writeUTF("현재시간 : " + strTime);

            }else if(msg.contentEquals("lotto")) {
               Set<Integer> set = new HashSet<>();
               while(set.size() < 7) {
                  set.add((int) (Math.random() *45+1));
               }
               String strLotto = set.toString();
               dos.writeUTF("오늘의 로또 : " + strLotto);

            }else if(msg.contentEquals("wise")) {
               String[] wise = new String[] {"Seeing is believing.", 
                     "Whatever you do, make it pay.", 
                     "You will never know until you try.", 
                     " No sweat, no sweet.",
               "Let bygones be bygones."};
               int index = (int)Math.random()*5;            
               String strWise = wise[index];
               dos.writeUTF("오늘의 운세 : " + strWise);            
            }else {
               dos.writeUTF("다시 입력해주세요.");
            }

            dos.flush();
         }catch(Exception e){
            
         }
      }
   }
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;

import javax.swing.JOptionPane;

public class Client4 {
	public static void main(String[] args) {

		try {
			Socket sock  = new Socket("192.168.60.28", 50000); //192.168.60.28 //127.0.0.1
			DataInputStream dis = new DataInputStream(sock.getInputStream());
			DataOutputStream dos = new DataOutputStream(sock.getOutputStream());
			
			while(true) {

				System.out.println(dis.readUTF());
				
				dos.writeUTF(JOptionPane.showInputDialog("입력창"));
				dos.flush();
		
				System.out.println(dis.readUTF());
			}
			
		}catch(Exception e) {
			e.printStackTrace();
			
		}
		
	}
}

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JOptionPane;

public class Server4 {
	public static void main(String[] args) throws Exception { //실습하는 동안만 throws

		ServerSocket server = new ServerSocket(50000);
		System.out.println("서버가 구동되었습니다.");

		while(true) {
			try {
				Socket sock = server.accept();//accept리턴값을 받을 변수 만들기
				new TLWThread(sock).start();
			}catch(Exception e) {

			}

		}
	}
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.text.SimpleDateFormat;

public class TLWThread extends Thread {

	private Socket sock;
	DataInputStream dis;
	DataOutputStream dos;

	public TLWThread(Socket sock) {
		this.sock = sock;
	}

	public void run() {
		System.out.println(sock.getInetAddress() + " 에서 연결하였습니다.");///192.168.60.19 에서 연결하였습니다.

		try {
			dis = new DataInputStream(sock.getInputStream());
		} catch (IOException e) {
			e.printStackTrace();
		}

		try {
			dos = new DataOutputStream(sock.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
		}

		while(true) {
			try {
				dos.writeUTF("time/lotto/wise 중 하나를 입력해주세요");

				String msg = dis.readUTF(); // 축약시 if문 조건 넘어 갈때마다 값 입력 받아야함

				if(msg.contentEquals("time")) {	

					SimpleDateFormat sdf = new SimpleDateFormat("yyyy년MM월dd일 hh시mm분ss초");				
					String strTime = sdf.format(System.currentTimeMillis());

					dos.writeUTF("현재시간 : "+ strTime); 

				}else if(msg.contentEquals("lotto")) {

					int[] lotto = new int[45];
					for(int i=0; i<lotto.length; i++) {
						lotto[i]=i+1;
					}
					for(int i =0; i< 500; i++) {
						int x = (int)(Math.random()*45);
						int y = (int)(Math.random()*45);			
						int tmp = lotto[x];
						lotto[x] = lotto[y];
						lotto[y] = tmp;
					}
					String printLt =
							"("+lotto[0]+")	("+lotto[1]+")	("+lotto[2]+")	("+lotto[3]+")	("+lotto[4]+")	("+lotto[5]+")";

					dos.writeUTF("로또번호 : "+printLt); 

				}else if(msg.contentEquals("wise")) {
					String[] str =new String[] {
							"To be conscious that you are ignorant is a great step to knowledge. -Benjamin Disraeli-",
							"Paradise is where I am. -Voltaire-",
							"You may be disappointed if you fail, but you are doomed if you don't try. -Beverly Sills-"
					};

					dos.writeUTF("오늘의명언 : "+str[(int)(Math.random()*3)]); 

				}else {
					dos.writeUTF("입력값을 확인해 주세요"); 
				}
				dos.flush();
			}catch(Exception e){
			}
		}

	}
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;

import javax.swing.JOptionPane;

public class Client4 {
	public static void main(String[] args) {

		try {
			Socket sock  = new Socket("127.0.0.1", 50000); //192.168.60.28 //127.0.0.1
			DataInputStream dis = new DataInputStream(sock.getInputStream());
			DataOutputStream dos = new DataOutputStream(sock.getOutputStream());
			
			while(true) {

				System.out.println(dis.readUTF());
				
				dos.writeUTF(JOptionPane.showInputDialog("입력창"));
				dos.flush();
		
				System.out.println(dis.readUTF());
			}
			
		}catch(Exception e) {
			e.printStackTrace();
			
		}
		
	}
}

질의응답

import java.util.Scanner;

class A{
}

public class Temp {
	public static void main(String[] args) {
		A a = new A(); // 인스턴스의 주소를 담는다
		System.out.println(a); //A@15db9742, 자바는 주소를 숨김, 그 대신에 고유값을 보여줌
		System.out.println(a.toString());//암묵적문법,결과는 같은 문법
		//.toString은 Object에서 상속받은 기능
        //만드는 사람이 오버라이드를 어떻게 했느냐에 따라 달라짐
		
		Scanner sc = new Scanner(System.in);
		System.out.println(sc);

		int[] arr = new int[3];
		System.out.println(arr);
		
//		List<Integer> li = new ArrayList;
	}
}

 

+ Recent posts