美文网首页
4 多线程00

4 多线程00

作者: 一枝妖孽 | 来源:发表于2018-06-10 21:20 被阅读0次

    一 多线程的创建

    1、thread/runnable
    thread:继承Thread类
    runnable:实现Runnable接口

    2、两种启动线程方式的区别

    共同点:必须通过Thread来产生线程,然后调用start方法来开启线程
    不同点:接口比继承更灵活;
    如果需要开启多个线程,runnable实现整个资源的共享,继承thread的话,需要new 多个线程。
    大多通过实现Runnable接口来实现多线程。适合多个相同代码处理统一资源的复用

    3、start方法和run方法的区别

    strat/run
    start开启一个线程,该线程为就绪状态,
    总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行

    二 线程间通信

    1、synchronized关键字【关键】

    1)synchronized对象锁【锁住的是当前对象】
    2)synchronized来实现线程间通信【通过不同的线程来共享同一个对象来进行锁的管理】
    3)synchronized/volatile 【二者区别】
    当一个变量没有修饰时,在单个线程中获取到的值实际为其在线程中拷贝的值,而非主内存中的值。
    volatile 不允许线程将一个变量从主内存中拷贝到自己的空间
    synchronized 锁住一个对象后,其他线程无法进入。同步主内存中的数据,之后执行自己的代码,再更新主内存中的数据,其他线程也更新该变量的值。

    synchronized:可以使用在类,方法,代码块,变量上,占用资源略多
    volatile:只能使用在变量上,更高效

    4)synchronized/lock
    synchronized:用法上
    lock:需要指定起始位置【自己调用lock.lock();//得到锁 lock.unlock();// 释放锁】,一般需要在finnally中UnLock.

    效率:synchronized托管给JVM虚拟机执行的,Lock我们java代码自己写的控制代码,
    synchronized相对低效
    synchronized采用悲观锁,Lock是CPU乐观锁

    悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
    乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。
    两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

    2、sleep/wait
    锁:sleep是Thread native方法,它在设定时间内阻塞线程的执行,不会改变线程的锁的持有情况。而wait方法需要锁来控制的。
    sleep()
    sleep() 方法是线程类(Thread)的静态方法,让调用线程进入睡眠状态,让出执行机会给其他线程,等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争cpu的执行时间。
    因为sleep() 是static静态的方法,他不能改变对象的机锁,【当一个synchronized块中调用了sleep() 方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象。】
    wait()
    wait()是Object类的方法,当一个线程执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其他线程能够访问,可以通过notify,notifyAll方法来唤醒等待的线程

    3、wait/notify机制
    锁:wait定义在Object中的,需要在同步代码块中调用,调用完成之后会释放锁,并进入锁对象的等待队列。
    需要其他线程调用notify方法释放锁之后,它才能重新竞争这个锁。

    三 线程池

    1、好处
    1)降低资源消耗【通过重复利用已经创建的线程,降低重复创建或者销毁线程所带来的消耗】
    2)提高响应速度【不需要等到线程创建,即可立即执行】
    3)提高线程的可管理性【可以进行统一的分配】

    2、ThreadPoolExecutor

    new ThreadPoolExecutor(corePoolSize,maximumPoolSize,
    keepAliveTime,milliseconds,unnableTaskQueue,handler);
    1)corePoolSize 线程池的基本大小
    2)maximumPoolSize 最大所能容纳的线程大小【】
    3)keepAliveTime 线程保持存活的时间
    4)milliseconds 时间单位
    5)runnableTaskQueue 线程阻塞队列
    6)ThreadFactory 创建线程的工厂类
    7)handler 饱和策略

    创建线程池--->提交任务
    线程池的隐患之处,我们没有办法判断该任务是否执行成功

    3、线程池的工作流程
    1)首先线程池判断基本线程池是否已满
    2)其次线程池判断工作队列是否已满
    3)最后线程池判断整个线程池是否已满

    相关文章

      网友评论

          本文标题:4 多线程00

          本文链接:https://www.haomeiwen.com/subject/zohfeftx.html