티스토리 뷰

LANGUAGE/JAVA

[JAVA] synchronized,Thread,제너릭

찰떡쿠키부스트 2017. 11. 15. 11:09

 

# synchronized


 실제로 실행해보고 결과 비교해보면 안다.
 


멀티쓰레드


========================
class ManyClient{
 StringBuffer str=new StringBuffer("ABCDE");
 public static void main(String args[]) throws InterruptedException{
 ManyClient mc=new ManyClient();
 mc.makeThread("가나다라마");
mc.makeThread("abcde");
 Thread.sleep(3000);
 }
 public void makeThread(final String s){
 Thread t=new Thread(){
 public void run(){
 addStr(s);
 }
 };
 t.start();
 }
 public void addStr(String other){
 for(int i=0; i<other.length(); i++){
 try{
 str.append(other.charAt(i));
 System.out.println("Str : "+str);
 Thread.sleep(100);
 }catch(Exception e){}
 }
 }
}


synchronized 적용된 멀티쓰레드


===================================
class ManyClient{
 StringBuffer str=new StringBuffer("ABCDE");
 public static void main(String args[]) throws InterruptedException{
 ManyClient mc=new ManyClient();
 mc.makeThread("가나다라마");
mc.makeThread("abcde");
 Thread.sleep(3000);
 }
 public void makeThread(final String s){
 Thread t=new Thread(){
 public void run(){
 addStr(s);
 }
 };
 t.start();
 }
 synchronized public void addStr(String other){
 for(int i=0; i<other.length(); i++){
 try{
 str.append(other.charAt(i));
 System.out.println("Str : "+str);
 Thread.sleep(100);
 }catch(Exception e){}
 }
 }
}




synchronized 블록 적용된 멀티쓰레드


===================================
class ManyClient{
 StringBuffer str=new StringBuffer("ABCDE");
 public static void main(String args[]) throws InterruptedException{
 ManyClient mc=new ManyClient();
 mc.makeThread("가나다라마");
mc.makeThread("abcde");
 Thread.sleep(3000);
 }
 public void makeThread(final String s){
 Thread t=new Thread(){
 public void run(){
 addStr(s);
 }
 };
 t.start();
 }
 public void addStr(String other){
 synchronized(str){
 for(int i=0; i<other.length(); i++){
 try{
 str.append(other.charAt(i));
 System.out.println("Str : "+str);
 Thread.sleep(100);
 }catch(Exception e){}
 }
 }
 }
}


쓰레드의 협조 ? wait/notify/notifyAll
synchronized제한자는 wait(), notify() 메서드와 함께 사용되어
스레드의 수행 순서를 조절할 때 활용된다.
예를 들어, 데이터를 저장하는 영역은 두 스레드가 공유하고,
첫 번째 스레드가 그 데이터 영역에 데이터를
저장하면 두 번째 스레드가 그 데이터를 읽어 정해진 처리를 하는 경우에
이 두 스레드는 동시에 수행될 수 없으며, 반드시 첫번째 스레드가 먼저,
수행되어 데이터 영역에 데이터를 저장해야 한다.
또 데이터 영역 크기가 제한되어 있으므로 적절한 시기에
두 번째 스레드가 수행되어 데이터를 사용해야 한다.
바로 이런 경우에 synchronized제한자와 wait(), notify()를 활용할 수 있다.




 ~~쓰레드 한번 복습해보자~~
 
 
 


멀티쓰레드 생성 및 실행


============================
class A extends Thread{
 String msg;
 A(String s){ msg=s; }
 public void run(){
 for(;;){
 System.out.print(msg);
 }
 }
}
class B{
 public static void main(String args[]){
 A t1=new A("A");
 A t2=new A("B");
 t1.start(); t2.start();
 }
}



쓰레드이름 얻어오기


===================================
class A extends Thread{
 String msg;
 A(String s){ msg=s; }
 public void run(){
 System.out.println(this.getName());
 }
}
class B{
 public static void main(String args[]){
 System.out.println(Thread.currentThread().getName());
 // 현재쓰레드(이경우에는 메인쓰레드) 이름보기
 A t1=new A("A");
 A t2=new A("B");
 t1.start(); t2.start();
 }
}




쓰레드 이름 바꾸기


===================================
class A extends Thread{
  A(String s){ super(s); }
 public void run(){
 System.out.println(getName()+"쓰레드");
 }
}
class B{
 public static void main(String args[]){
 System.out.println(Thread.currentThread().getName());
 A t1=new A("일번");
 A t2=new A("이번");
 t1.start(); t2.start();
 }
}




현재 활동중인 쓰레드 보기


==================================
class A extends Thread{
  A(String s){ super(s); }
 public void run(){}
}
class B{
 public static void main(String args[]){
 A t1=new A("일번");
 A t2=new A("이번");
 t1.start(); t2.start();
 t1.
 System.out.println(Thread.activeCount());
 }


 
 
 
 enumerate(); 비어있는배열에 쓰레드 주소값을 다 넣음
=====================================
 class A extends Thread{
 A(String s){
 super(s);
 }
 public void run(){
 try{
 Thread.sleep(1000);
 }catch(Exception e){}
 }
}
class B{
 public static void main(String args[]){
 A t1=new A("일번");
 A t2=new A("이번");
 t1.start();
 t2.start();
 Thread[] tarray=new Thread[Thread.activeCount()];
 Thread.enumerate(tarray);
 for(Thread t : tarray){
 System.out.println(t.getName());
 }
 }
}



Thread.yield(); --> 양보하는 메서드


====================
예제는 따로 없다. 걍 양보한다.
 
 
 
 
 


join(); --> 쓰레드 다 끝날때까지 기다려.


=====================
class SimpleThread extends Thread {
 public SimpleThread(String s) {
 super(s);
 }
 public void run() {
 for(int i=0; i<5; i++) {
 if(getName().equals("Disney Land")) JoinTest.tour=0;
 else JoinTest.tour=1;
 try {sleep(1000); } catch (Exception e) { }
 }
 }
}
class JoinTest {
 static int tour; // JoinTest의 정적 변수
public static void main(String[] a) {
 SimpleThread t1= new SimpleThread("Disney Land");
 SimpleThread t2= new SimpleThread("tt Hong Kong");
 t1.start(); t2.start();
 try { t1.join(); t2.join(); } catch(Exception e){
  e.printStackTrace(); }
 if(tour==0) System.out.println("Let´s go! Disney Land!");
 else System.out.println("Let´s go! Hong Kong!");
 }
}
 

 

 


 
 
join 실제 예제.


=================================
 class A extends Thread{
 int first; int last; int sum;
 A(int a,int b){ first=a; last=b; }
 public void run() {
  for(int num=first; num<=last; num++){
   sum+=num;
   }
 }
}
class B{
 public static void main(String[] a) {
 A t1=new A(1,50);
 A t2=new A(51,100);
 t1.start(); t2.start();
 try { t1.join(); t2.join(); } catch(Exception e){
 e.printStackTrace(); }
 System.out.println(t1.sum+t2.sum);
 }
}
 
 
 
 
 


interrupt  --> interruptedException 자동 호출(sleep,join 무력화)


===============================
class Echo extends Thread {
 private int waitTime; // in millisecs
 public Echo(String word, int waitTime) {
 super(word);
 this.waitTime = waitTime;
 }
 public void run( ) {
 for(int i=0; i<10; i++) {
 System.out.print(getName()+">"+i+"\t");
 try {
sleep(waitTime); //처음에만 5초 자야되는데 e1.interrupt() 때매못자고 바로밑에 실행
}catch (InterruptedException e){
 System.out.print(getName()+":인터럽트발생\t");
 }
 }
 }
 public static void main(String[] args) {
 Echo e1 = new Echo("Foo", 5000);
 Echo e2 = new Echo("Bar", 5000);
 e1.start(); e1.interrupt(); e2.start(); e2.interrupt();
 }
}





생산자 소비자 패텬 원리(깨우고 자기는 자러감)


========================================
class Echo extends Thread{
 private Thread t;

public Echo(String word){
 super(word);
 }
 public void setNextThread(Thread t){
 this.t=t;
 }
 public void run(){
 for(int i=0; i<10; i++){
 try{sleep(3000);}catch(InterruptedException e){}
 System.out.print("Thread"+getName()+">"+i+"\t");
 t.interrupt();
 }
 }
 public static void main(String[] args){
 Echo e1 = new Echo("일");
 Echo e2 = new Echo("이");
 Echo e3 = new Echo("삼");
 e1.setNextThread(e2);
 e2.setNextThread(e3);
 e3.setNextThread(e1);
 e1.start(); e2.start(); e3.start();
 e1.interrupt();
 }
}
 
 
 
 
 
 


실제 생산자 소비자 패턴 예제


==========================================
 import java.util.*;
class Producer extends Thread{
 Resource source;
 public Producer(String n, Resource s){
 super(n);
 source=s;
 }
 public void run(){
 for(char ch='A'; ch<'J'; ch++){
 System.out.println(getName()+"가 제품["+ch+"]를 생산했다.");
source.put(ch);
 }
 }
}
class Consumer extends Thread{
 Resource source;
 public Consumer(String n, Resource s){
 super(n);
 source=s;
 }
 public void run(){
 char getch=' ';
 for(char ch='A'; ch<'J'; ch++){
 getch=source.get();
 System.out.println(getName()+"가 제품["+getch+"]를 소비했다.");
 }
 }
}
class Resource{
 Vector<Character> vec;
 static Producer p;
 static Consumer c;
 public Resource(){
 vec=new Vector<>();
 }
 public void put(char ch){
 while(vec.size()==3){
 try{
 Thread.sleep(5000);
 }catch(InterruptedException e){}
 }
 vec.add(ch);
 System.out.println("창고에 제품["+ch+"]가 들어왔다. 재고수량:"+vec.size());
 c.interrupt();
 }
 public char get(){
 while(vec.size()==0){
 try{Thread.sleep(5000);}catch(InterruptedException e){}
 }
 char ch=vec.remove(0);
 System.out.println("창고에 제품["+ch+"]가 나갔다. 재고수량:"+vec.size());
 p.interrupt();
 return ch;
 }
 public static void main(String args[]){
 Resource r=new Resource();
 p=new Producer("생산자",r);
 c=new Consumer("소비자",r);
 p.start(); c.start();
 }
}







interrupt()를 쓰면 주소값을 일일이 다 알아야되기때문에 생산자와 소비자가많아지면 귀찮아진다.그래서 synchronized메서드에서만 사용할 수 있는
sleep()대신 wait() c.interrupt() 대신 notifyAll()을 사용한다.


================================
 import java.util.*;
 class WarehouseControl{
 public static void main(String args[]){
 MyWarehouse myWarehouse=new MyWarehouse();
 Producer p=new Producer(myWarehouse);
 Consumer c=new Consumer(myWarehouse);
 p.start(); c.start();
 }
}
class MyWarehouse{
 Vector vec;
 public MyWarehouse(){
 vec=new Vector();
 }
 synchronized void put(char ch){
 while(vec.size()==3){
 try{
 wait();
 }catch(InterruptedException ie){}
 }
 vec.add(new Character(ch));
 System.out.print("창고에 제품 "+ch+"가 들어왔습니다.");
System.out.println("재고수량 : "+vec.size());
 notifyAll();
 }
 synchronized char get(){
 while(vec.size()==0){
 try{
 wait();
 }catch(InterruptedException ie){}
 }
 Character ch=(Character)vec.remove(0);
 System.out.print("창고에 제품 "+ch+"가 나갔습니다.");
System.out.println("재고수량 : "+vec.size());
 notifyAll();
 return ch.charValue();
 }
}
class Producer extends Thread{
 private MyWarehouse myWarehouse;
 public Producer(MyWarehouse vec){
 myWarehouse=vec;
 }
 public void run(){
 for(char ch=´A´; ch<=´Z´; ch++){
 System.out.println("생산자가 제품 "+ch+"(을)를 생산했습니다.");
myWarehouse.put(ch);
 }
 }
}
class Consumer extends Thread{
 private MyWarehouse myWarehouse;
 public Consumer(MyWarehouse vec){
 myWarehouse=vec;
 }
 public void run(){
 char ch;
 for(int i=1; i<=26 ; i++){
 ch=myWarehouse.get();
 System.out.println("소비자가 제품 "+ch+"(을)를 소비했습니다.");
 }
 }
}
 
 


collection 동기화 처리 메서드
synchronizedList
 
 ~~하기전에 제너릭 복습한번 하고가자~~
 
 


제너릭 클래스


=============================
 class A<T>{
 T o;
 void set(T o){ this.o=o; }
 T get(){ return o; }
}
class B{
 public static void main(String args[]){
 A<String> o1=new A<>();
 o1.set("aa");
 System.out.println(o1.get()); // aa
 A<Integer> o2=new A<>();
 o2.set(100);
 System.out.println(o2.get()); // 100
 }
}

 

 

제너릭 메서드(반환형 앞에 제너릭 선언)


==================================
class A{
 static <T> T get(T obj){
 return obj;
 }
}
class B{
 public static void main(String args[]){
 A o=new A();
 String s=o.get("aaa");
 int i=o.get(100);
 System.out.println(s);
 System.out.println(i);
 }
}

 이제 다시
 collection 동기화 처리 메서드
 synchronizedList
 
public static <T> List<T> synchronizedList(List<T> list)

 

'LANGUAGE > JAVA' 카테고리의 다른 글

[JAVA] jdk7의 신기능  (0) 2017.11.15
[JAVA] enum,Graphics  (0) 2017.11.15
[JAVA] io,network  (0) 2017.11.15
[JAVA] awt.menu ,io  (0) 2017.11.15
[JAVA] Calendar 객체  (0) 2017.11.15
댓글