작업 중 ThreadLocal과 스레드 탱크를 사용한 구덩이를 기록하다

3211 단어 JavaSE
최근에 처리 데이터가 필요합니다. 자바 프로그램을 작성해야 합니다. 여러 라인으로 데이터를 빨리 처리할 수 있다고 생각해서threadLocal과 라인 풀을 사용했습니다. 그러나 라인 풀에 대한 이해가 깊지 않아서 버그를 만났습니다.
코드(약자):
public class Message {

    private static ThreadLocal threadLocal = new ThreadLocal(){
        @Override
        protected Connection initialValue() {
            return HiveClient.getConnection();
        }
    };

    public static void main(String[] args) {

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,20,20, TimeUnit.SECONDS,new LinkedBlockingQueue(100));
        for (int i = 0; i< 10 ;i ++){
            threadPoolExecutor.execute(new Handle(threadLocal));
        }
    }

}




public class Handle implements  Runnable {

    private ThreadLocal threadLocal;
    private Connection connection;

    public Handle(ThreadLocal threadLocal){
        this.threadLocal = threadLocal;
    }

    public void handle(String sql){
        connection = threadLocal.get();
        try{
          PreparedStatement prepareStatement  =   connection.prepareStatement(sql);
          prepareStatement.execute();
          //    

        }catch (Exception e){

        }finally {
            try {
                connection.close(); //        ,       。
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public void run(){
        String sql = "xxxxxx";
        handle(sql);
    }

}

질문:
다섯 개의 스레드를 처리한 후 SASL authentication not complete를 꺼냅니다.
이유:
자신이 스레드 탱크에 대한 이해가 깊지 않아handle 방법에서 데이터를 처리한 후에connection·를 닫았습니다. 스레드 탱크는 코어 수량의 스레드를 계속 복용하는 것이기 때문에 임무를 처리한 후에 회수하지 않습니다.threadLocal은 스레드와 연결되어 있기 때문에 다음 임무는 스레드 탱크를 복용할 때threadLocal을 사용합니다.get () 방법은 이전 작업이 연결된connection을 닫았기 때문에 이상을 던집니다.
 
ThreadLocal 해결:
먼저 ThreadLocal의 get 방법을 살펴보십시오.
 public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

getmap 방법을 사용해서 ThreadLocalMap 클래스를 가져오고 ThreadLocalMap 클래스에서 ThreaLocal의 실례 이름이 키의value를 가져옵니다. 만약 맵이 비어 있다면 초기 값을 설정하고 되돌려줍니다.
  private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }

 T value = initialValue(); 이 초기 값은 new ThreadLocal에서 설정됩니다.getMap 방법을 보십시오.
 ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
ThreadLocal.ThreadLocalMap threadLocals = null;

마지막으로threadLocal 클래스 안에ThreadLocalMap 클래스가 있는데 getMap 방법은 바로 이 클래스를 얻는 것이다.
스레드 풀 해결:
시간이 좀 지나서 보충하다.
 
 
 
 
 
 

좋은 웹페이지 즐겨찾기