多线程使用小结

2018-04-17  本文已影响0人  开心就好_4ad7

    在多线程编程中,解决线程之间的协作、数据共享等问题,不可避免需要用到volatitle、synchronize、Condition、ThreadLocal等,接下简单介绍一下:

一、volatitle

    主要解决线程间数据可见性及指令重排序,具体可以参考volatitle随记,这里不在详细介绍。

二:Condition

    Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition的await()、signal()这种方式实现线程间协作更加安全和高效。因此通常来说比较推荐使用Condition,阻塞队列实际上是使用了Condition来模拟线程间协作,Condition是一个接口,它提供了以下几个方法:

void await() throws InterruptedException;
boolean awaitUntil(Date deadline) throws InterruptedException;
long awaitNanos(long nanosTimeout) throws InterruptedException;
void awaitUninterruptibly();
void signal();
void signalAll();
public class ConditionTest {
    public final static Lock lock = new ReentrantLock();
    public final static Condition condition = lock.newCondition();
    
    public static void main(String[] args) {
        new Consumer().start();
        new Producer().start();
    }
    
    public static class Consumer extends Thread{
        
        public void run(){
            while(true){
                consume();
            }
        }
        
        private void consume(){
            lock.lock();
            System.out.println("wait singal..");
            try {
                condition.await();
                System.out.println("consume..");
            } catch (InterruptedException e) {
            }finally{
                lock.unlock();
            }
        }
    }
    
    public static class Producer extends Thread{
        public void run(){
            while(true){
                product();
            }
        }
        
        private void product(){
            try{
                lock.lock();
                Thread.sleep(100);
                System.out.println("product...");
                condition.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                lock.unlock();
            }
        }
    }
}

三:ThreadLocal

    多线程并发执行时,需要数据共享,所以才有volatitle变量解决线程之间数据共享问题,也有了锁的同步机制,确保数据的准确性,而有的时候,线程数据并不需要共享,只需要线程自己维护即可,而ThreadLocal就是用来做线程之间数据隔离的,在介绍ThreadLocal使用前,简单了解一下源码:
    先我们来看一下ThreadLocal类是如何为每个线程创建一个变量的副本的。

/**
     * Returns the value in the current thread's copy of this
     * thread-local variable.  If the variable has no value for the
     * current thread, it is first initialized to the value returned
     * by an invocation of the {@link #initialValue} method.
     *
     * @return the current thread's value of this thread-local
     */
    public T get() {
        Thread t = Thread.currentThread();//1
        ThreadLocalMap map = getMap(t);//2
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();//3
    }
/**
         * The entries in this hash map extend WeakReference, using
         * its main ref field as the key (which is always a
         * ThreadLocal object).  Note that null keys (i.e. entry.get()
         * == null) mean that the key is no longer referenced, so the
         * entry can be expunged from table.  Such entries are referred to
         * as "stale entries" in the code that follows.
         */
        static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }
总结:
public class ThreadLocalTest {
    private ThreadLocal<Map<String,String>> paramsLocal = new ThreadLocal<Map<String,String>>();
    public void validate(Request request) throws ApiRuleException {
        try{
            if(paramsLocal.get() == null){
                paramsLocal.set(new HashMap<>());
            }
            Map<String,String> params = paramsLocal.get();
            params.put("source","source");
            params.put("source1","source1");
                //做其它事情
        }finally{
            paramsLocal.get().clear();//清除Map数据
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读