wait 상태의 Thread 를 종료하고 싶을 때.. interrupt 를 사용하자.
뭐.. 스레드를 종료할 때 항상 interrupt 를 사용해서 종료하면 좋다고는 함.

1. SampleThread.java
- interrupt 를 사용해서 thread 를 종료한다.
package study.interrupt;

import java.util.concurrent.BlockingQueue;

public class SampleThread extends Thread {

 private final BlockingQueue<String> queue;
 
 SampleThread(BlockingQueue<String> queue) {
  this.queue = queue;
 }
 
 @Override
 public void run() {
  try {
  
   int index = 0;
  
   while(!Thread.currentThread().isInterrupted()) {
    queue.put("" + index);
    System.out.print(index + " : ");
    index ++;
   }
  } catch(InterruptedException e) {
   System.out.println();
  }
 }
 
 public void cancel() {
  interrupt();
 }

}

2. 테스트
package study.interrupt;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class Launcher {

 public static void main(String[] args) {
  BlockingQueue<String> queue = new ArrayBlockingQueue(10);
 
  SampleThread t = new SampleThread(queue);
  t.start();
 
  try {
   Thread.sleep(3000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  t.cancel();

  for(String str : queue) {
   System.out.print(str + " : " );
  }

 }
}

Posted by 짱가쟁이
이번 예제도 "Excutor를 사용한 thread pool 샘플" 을 토대로 작성됨
Executor 를 상속받은 ExecutorService 를 사용하여 pool 의 동작 주기를 관리한다.
void stop(..) 함수는 java api 를 참조함..

1. ConsumerThread.java 수정

package study.concurrrency;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;

public class ConsumerThread implements Runnable {

 Thread thread;

 private static final ExecutorService pool = Executors.newFixedThreadPool(10);
 
 public void start() {
  thread = new Thread(this);
  thread.start();
 }
 
 // java api 참조
 void stop(ExecutorService pool) {
  pool.shutdown(); // Disable new tasks from being submitted
 
  try {
   // Wait a while for existing tasks to terminate
   if (! pool.awaitTermination(60, TimeUnit.SECONDS)) {
    pool.shutdownNow(); // Cancel currently executing tasks
    // Wait a while for tasks to respond to being cancelled
    if (! pool.awaitTermination(60, TimeUnit.SECONDS))
     System.err.println("Pool did not terminate");
   }
  } catch (InterruptedException ie) {
   // (Re-) Cancel if current thread also interrupted
   pool.shutdownNow();
   // Preserve interrupt status
   Thread.currentThread().interrupt();
  }
 }
 
 @Override
 public void run() {
  // TODO Auto-generated method stub 
  while(!pool.isShutdown()) { 
   try {
    pool.execute(new Worker(BlockingQueueSample.getInstance().getData()));
   } catch(RejectedExecutionException e) {
    if(!pool.isShutdown()) {
     System.out.println("작업이 거부당했구만..");
    }
   }
  }
 }
}




 

 

Posted by 짱가쟁이
전에 작성 했던.. "BolckingQueue 와 producer-consumer 패던 활용법 " 예제를 토대로 Executor로 thread pool 예제를 작성거임.
 
1. ConsumerThread.java  수정
  - 등록된 상품이 있으면 무식하게 가져와서 화면에 보여주던 놈을 조금 수정해서 Worker.java 라는 넘으로 Job을 위임함.
  - Executors.newFixedThreadPool 를 사용해 pool 생성 후 Worker.java 를 실행함.
package study.concurrrency;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class ConsumerThread implements Runnable {

 Thread thread;

 private static final Executor exec = Executors.newFixedThreadPool(10);
 
 public void start() {
  thread = new Thread(this);
  thread.start();
 }
 
 @Override
 public void run() {
  // TODO Auto-generated method stub 
  while(true) {   
   exec.execute(new Worker(BlockingQueueSample.getInstance().getData()));
  }
 }
}

2. Worker.java
  - 넘어온 상품(job)을 무식하게 화면에 보여주는 Thread.
package study.concurrrency;

public class Worker implements Runnable {

 String str;
 
 public Worker(String str) {
  this.str = str;
 }
 @Override
 public void run() {
  // TODO Auto-generated method stub
  System.out.println(str);
  try {
   Thread.sleep(500);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 
 }

}

3. 실행
  - 예전 코드 그대로 실행하면 됨.

4. 결과
  - 위에서 설정했던 pool 사이즈 만큼 job 들이 실행되는 것을 확인할 수 있음.

 
Posted by 짱가쟁이
출처

1. BlockingQueueSample.java
 - 등록된 상품이 있으면 ConsumerThread.java 요넘이 가져가고.. 없으면 대기 시킴.
package study.concurrrency;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueSample {

 static BlockingQueueSample instance;
 
 BlockingQueue queue = new ArrayBlockingQueue(10);
 
 public synchronized static BlockingQueueSample getInstance() {
  if(instance == null)
   instance = new BlockingQueueSample();
 
  return instance;
 }
 
 public void setData(String arg) {
  try {
   queue.put(arg);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
 
 public String getData() {
  try {
   return (String)queue.take();
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return null;
 }
}

2. ConsumerThread.java
 - BlockingQueueSample.java 에 등록된 상품이 있으면 무조건 가져오는 무식한 놈임. 이런 소비자만 있으면 무쟈게 행복할듯..
package study.concurrrency;

public class ConsumerThread implements Runnable {

 Thread thread;

 public void start() {
  thread = new Thread(this);
  thread.start();
 }
 
 @Override
 public void run() {
  // TODO Auto-generated method stub 

  while(true) { 
   System.out.println("aaa : " + BlockingQueueSample.getInstance().getData());
   System.out.println("aaa : " + BlockingQueueSample.getInstance().queue.size());
  
   try {
    Thread.sleep(500);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }
}

3. ProducerThread.java
 - 원하는 제품을 무식하게 만들어 주는 놈.
package study.concurrrency;

public class ProducerThread implements Runnable {

 Thread thread;

 String string;
 int time;
 
 public ProducerThread(String string, int time) {
  this.string = string;
  this.time = time;
 }
 public void start() {
  thread = new Thread(this);
  thread.start();
 }
 
 @Override
 public void run() {
  // TODO Auto-generated method stub 

  int index = 0;
 
  while(index<10) {
   index++;
  
   BlockingQueueSample.getInstance().setData(string + "[" + index + "]");
   try {
    Thread.sleep(time);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }
}

4. 테스트
ConsumerThread sample = new ConsumerThread();
sample.start();
 
ProducerThread p1 = new ProducerThread("가방", 1);
p1.start();
 
ProducerThread p2 = new ProducerThread("지갑", 1);
p2.start();

ps.
  위 예제를 참고로 Excutor를 사용해서 Thread Pool을 만들어 봐야 할듯.
Posted by 짱가쟁이
Posted by 짱가쟁이
ThreadLocal
하나의 쓰레드에서 객체를 전파하는 방법으로 파라미터를 사용하기 않고 코드에서 동일한 객체를 사용할 수 있게 해준다.

활용 예)
- 객체를 쓰레드에 안전하게 해준다.
- 쓰레드 단위로 트랜잭션 컨텍스트를 관리하고자 할때 사용.
(static으로 선언된 ThreadLoacl 변수에 트랜잭션 컨텍스트를 넣어두면 쓰레드에 안전하게 사용가능)
- ThreadLocal을 사용하여 공유 데이터를 사용할 때 현재 실행중인 스레드의 정보를 넘겨줘야 할 필요는 없지만, 이런 방법은 해당 프레임웍에 대한 의존성을 가지고 된다.
- 전역변수처럼 사용되기 때문에 일반적인 전역 변수가 갖는 단점처럼 재사용성을 떨어뜨릴 수 있고, 객체 간에 눈에 보이지 않는 연결 관계를 만들어내기 쉽기 때문에 애플리케이션에 어떤 영향을 미치는지 정확하게 알고 사용해야 한다.

사용 예)

ThreadLocalClass.java
public class ThreadLocalClass {

    public static ThreadLocal<UserInfo> local = new ThreadLocal<UserInfo>();
}

WorkerRunnable.java
- ThreadLocal 변수 사용
- 객체는 할당한 쓰레드에서만 사용할 수 있다.
public class WorkerRunnable implements Runnable {

    private String name;
  
    public WorkerRunnable(String name) {
        this.name = name;      
    }
  
    public void setObject() {
        UserInfo info = new UserInfo();
        info.setName(name);      
        ThreadLocalClass.local.set(info);
    }
  
    @Override
    public void run() {
        setObject();

        while(true) {
            Business business = new Business();
          business.logic_01();
        }
    }
}

Business.java
- 객체 사용
public class Business {

    public void logic_01() {
        UserInfo user = ThreadLocalClass.local.get();
        System.out.println(Thread.currentThread().getName() + ":" + user.getName());
    }
}

UserInfo.java
- 데이터 객체
public class UserInfo {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    } 
}

Launcher.java
- 테스트 클래스
public class Launcher {

    public static void main(String[] args) {      
              
        for(int i = 0;i<10;i++) {
            WorkerRunnable w = new WorkerRunnable("bbaeggar : " + i);
            Thread t = new Thread(w);
            t.start();
        }
    }
}

Posted by 짱가쟁이
quartz를 사용하고 멀티쓰레드로 작업을 병렬로 처리하던중.. 작업지연으로 인해서 이전 작업이 끝나기도 전에 다음 작업이 시작된다. 뭐.. 가장 좋은 방법은 단순하게 쿼즈가 실행하는 쓰레드 하나만 사용하면 좋것지만.. DB 성능 문제로 인해서 꼭 병렬처리를 수행해야 한다면.. ?? 이때.. Callable 인터페이스를 사용하여 쓰레드의 결과값을 받을 수 있다.

Launcher.java
private final ExecutorService executor  = Executors.newFixedThreadPool(THEAD_SIZE);

public void excute() {
    Future[] future = new Future[THEAD_SIZE];
    for(int i = 0;i<THEAD_SIZE;i++) {
        future[i] = executor.submit(new WokerThread(synchData, 1, totalCount, reqVo));                       
    }
    for(int i = 0;i<THEAD_SIZE;i++) {
        info.info("[" + future[i].get() + "] 종료" );   
    }
}

Callable을 구현한 넘
import java.util.concurrent.Callable;

public class WokerThread implements Callable<String> {
  
    public String call() {       
        while(true) {           
            return (String)Thread.currentThread().getName();
        }
    }
}

위에 샘플은 단순한 사용방법을 구현했지만.. 다양한 방법으로 유용하게 사용할 수 있을듯.


Posted by 짱가쟁이
이전버튼 1 2 이전버튼