2018-12-19 java多线程

java学习

[toc]

第一章线程安全

1.1 ThreadLocal理解


/**
这是一个ThreadLoca的内部Map

涉及到3个类
Thread
ThreadLocal
ThreadLocal.ThreadLocalMap

关系:
一个Thread对象里面有一个ThreadLocal.ThreadLocalMap,相当于是一个线程就一个ThreadLocalMap对象.

这个ThreadLocalMap里面的key是ThreadLocal对象, value是传递进行来的值


**/

Thread.class里面
ThreadLocal.ThreadLocalMap threadLocals = null;
static class ThreadLocalMap {
    static class Entry extends WeakReference<ThreadLocal<?>> {
        Object value;
        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }
    }
/**
set 操作
**/
public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}
/**
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();
}
//通过当前线程,或者ThreadLocal
ThreadLocalMap getMap(Thread t) {
    //每一个线程 存一份ThreadLocal.ThreadLocalMap
    return t.threadLocals;
}

1.2 CAS

    代码块

1.3 AQS

LockSupport

    1.先说一下理解。 这个东西是一个许可。 就是 0/1 俩个信号量
    2.LockSupport.park() //获取许可
    3.LockSupport.unpark(Thread thread) //释放许可
    -------------------------------------------------    
    默认这个许可是被占用的。。
     public static void test1(){
        //许可默认是被占用的。。。
        LockSupport.park();
        System.out.println("线程一直处于阻塞状态。。");
    }
    
    
    ------------------------------------------------
     public static void test2(){
        //许可默认是被占用的。。。
        Thread thread = Thread.currentThread();
        //释放许可
        LockSupport.unpark(thread);
        //获取许可
        LockSupport.park();
        System.out.println("1.释放许可, 2,获取许可, 打印");
    }
    ------------------------------------------------
    public static void test3(){
        //LockSupport是不可重入 一个线程连续俩次 park 也会阻塞
        Thread thread = Thread.currentThread();
        //许可默认是被占用的。。。
        //释放许可
        LockSupport.unpark(thread);
        //得到许可
        LockSupport.park();
        
        System.out.println("可以打印");
        //再次获取许可。。失败
        LockSupport.park();
        System.out.println("不可以打印");
    }
    

ReentrantLock

    AQS核心是利用CAS的理论,结合双向队列(lock)和单向队列(Condition)来实现的。

1.4 volatile 线程安全吗?

    不安全的。还是存在i++的问题。

1.5 Callable 和 Runnable 区别

    /**
    Callable 是一个有返回值的的,一般结合Future使用。
    **/
    @FunctionalInterface
    public interface Callable<V> {
        /**
         * Computes a result, or throws an exception if unable to do so.
         *
         * @return computed result
         * @throws Exception if unable to compute a result
         */
        V call() throws Exception;
    }
    
    /**
    Runnalbe 是一个没有返回值的,正常线程的使用。
    **/
    @FunctionalInterface
    public interface Runnable {
        void run();
    }


1.6 Future 阻塞, 超时设置

    Future.get();//线程阻塞的。
    
    //线程阻塞,等待一段时间,然后抛出异常
    Future.get(long time,TimeUtil util);
    

1.7 ExecutorService 四种

    代码块

1.8 停止一个线程

    停止一个线程

1.9 多线程之间的通信和协作

    

1.10 ReentrantLock

详见上面<a href='#1.2 CAS'>ReentrantLock</a>

1.11 SynchronizedMap

    

1.12 HashMap

    

1.13 HashTable

    

1.14 并发框架

CopyOnWriteArrayList

    CopyOnWriteArrayList

CountDownLatch

    CountDownLatch

1.15 并发容器

CountDownLatch

    CountDownLatch

CyclicBarrie

    

1.16 线程池

Executors

    这个是创建的线程池, 也就是相当于创建Thread 肯定里面需要的是Runnable接口来的实线啦。
    
    //1.创建一个线程
     ExecutorService es = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            es.submit(()->{
                System.out.println(Thread.currentThread().getId());
            });
        }
    
    //2.创建一个固定大小的线程池
    ExecutorService es = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            es.submit(()->{
                System.out.println(Thread.currentThread().getId());
            });
        }
    
    //3.创建一个缓冲池的线程池,根据系统的内存
    ExecutorService es = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            es.submit(()->{
                System.out.println(Thread.currentThread().getId());
            });
        }
    //4.创建一个可以调度的线程池,这个特殊,可以延迟执行。。
    ScheduledExecutorService es = Executors.newScheduledThreadPool(3);
        for (int i = 0; i < 10; i++) {
            es.schedule(()->{
                log.info("{}",Thread.currentThread().getId());
            },new Random().nextInt(10),TimeUnit.SECONDS);
        }

ExecutorService

    执行线程的方法有俩个
    1.void execute(Runnable command);//没有返回值
    2.<T> Future<T> submit(Callable<T> task);//有返回值
    
    eg:
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    //Runnable接口
    executorService.execute(()-> {
            log.info("this is 没有返回值");
        });
    //Callable 接口
    Future<Integer> future = executorService.submit(()->{
        log.info("this is 有返回值");
        return 1;
    });
    Integer result = future.get();
    

ThreadPoolExecutor

    上面的是jdk为了方便定义的一些线程池,但是我们伟大的程序员怎么能不自己创建呢。。这个类就是自己创建线程池的源码。
    参数解释:
    corePoolSize:池中保留的线程数
    maximumPoolSize:池中最大的线程数
    keepAliveTime:当线程池中的线程大于corePoolSize时候,等待新任务之前的保留时间
    unit:上面的保留时间
    workQueue:工作队列,用于保留执行任务之前的任务。 LinkedBlockingQueue
        1.直接切换
        2.使用无界队列  LinkedBlockingQueue
        3.使用有界队列  ArrayBlockingQueue
    
    threadFactory:创建新线程的工厂 DefaultThreadFactory->new Thread()
    handler:拒绝策略 :线程池满啦,工作队列满啦。
        1.AbortPolicy 直接抛出异常 默认策略
        2.CallerRunsPolicy:用调用者所在的线程来执行任务;[没看懂]
        3.DiscardOldestPolicy 丢弃阻塞队列最前面任务,并且执行当前任务
        4.DiscardPolicy 丢弃任务
    
    Executors.newSingleThreadExecutor(); //里面的实现
    new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    
    

1.18 a

    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容