티스토리 뷰
# 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 |