java多线程学习

同步关键字synchronized


注:本博文synchronized 有时会简写成 sync
synchronized 同步关键字,自动释放锁,锁住的是对象,不是代码块
sync 声明在方法名上,锁定的是this对象(调用方法的那个对象)
sync 锁是可重入的(此线程可多次访问此对象的锁)
        本方法再次调用本方法
        本方法调用父类方法

死锁的模拟
    线程T1 持有锁A 等待B
    线程T2 持有锁B 等待A

可见性关键字volatile

volatile 保障可见性,不能代替sync,不能保障原子性,性能比sync高
    下面场景:
    主线程变量 V
    线程1 读变量V,继续跑一段时间
    线程2 写变量V,并同步至主线程
    现场1 读V,还是原来的V,原因是读的是此线程对变量的副本。
    加了volatile之后,线程2对比那里V做的修改,线程1也可以看见。

wait-notify

wait 让线程进入等待状态,同时释放锁,直到其它线程notify时,它才会重新运行。Object的方法,wait需要和while共用
notify 唤醒一个线程,但是不会释放锁,如果本身拿着对象的锁,wait也不会唤醒其他线程
notifyAll 唤醒所有wait的线程,所以这里也是说要用wait和while搭配的原因。
    A object.wait() //释放锁
    B object.nofity() //唤醒object锁的线程,此时没有释放锁
    B object.wait()  //释放此线程的锁
    A 执行 //得到锁  可以运行业务方法
    A object.notity()  //结束时唤醒object 锁的线程

简单示例:https://blog.csdn.net/xiaoluo5238/article/details/104358061

重入锁ReentrantLock

ReentrantLock 重入锁 可以实现 sync ,比sync灵活,需要手动释放锁
    new ReentrantLock();//随机分配锁
    new ReentrantLock(true);//声明公平锁 等待时间越长,得到锁的优先级越高
    lock.lock();//申请
    lock.unlock();//释放锁
    bool lockFlag = lock.tryLock();//尝试去拿锁,返回lock,如果为true,说明拿到锁,需要解锁
    bool lockFlag = lock.tryLock(5, TimeUnit.MINUTES);//尝试去拿锁,等待5分钟
    lock.lockInterruptibly(); 可被打断的等待锁,主线程调用此线程的 interrupt 方法。     
    
    
Lock的Condition  使用Condition的await()、signal()/signalAll() 代替 wait/notify,这种方式实现线程间协作更加安全和高效
    Condition putCondition = lock.newCondition();//实例
    putCondition.await();//与Object.wait方法一样,都是要与while共同使用,使线程等待,释放锁,直到putCondition.signal()或
                           putCondition.signalAll()才继续执行
    putCondition.signal();//唤醒 putCondition.await() 等待的线程

简单示例:https://blog.csdn.net/xiaoluo5238/article/details/104348598

 Condition示例:https://blog.csdn.net/xiaoluo5238/article/details/104359334

 

ThreadLocal

ThreadLocal
    线程内 threadLocal.set(), 只是当前线程能 threadLocal.get() 到
    只能设置一个对象,可set map对象。
    容易造成内存泄漏,每次使用完ThreadLocal,都调用它的remove()方法,清除数据

简单示例:https://blog.csdn.net/xiaoluo5238/article/details/104360178

多线程同步工具

CountDownLatch 线程间的通讯 -门栓 或 门闸 或 减数器
简单理解:等待 所有的门栓 打开后才能继续执行
     new CountDownLatch(3);//声明定义 多少个门栓,如果有3个,那个需要调用3次countDown()方法后,才能执行到await()方法
     countDownLatch.await();  //等待门栓全部打开,才会执行
     countDownLatch.countDown();//打开一个门栓
简单示例:https://blog.csdn.net/xiaoluo5238/article/details/104339788

Semaphore 信号量 信号量是保证同一时间内最大的访问数量(线程)
    Semaphore semaphore = new Semaphore(2);//同时申请的数量
    semaphore.acquire();//申请信号量
    semaphore.release();//释放信号量
简单示例:https://blog.csdn.net/xiaoluo5238/article/details/80310436

CyclicBarrier 循环栅栏
    new CyclicBarrier(num);//设置栅栏数
    new CyclicBarrier(num,Runnable)//设置栅栏数(目标数),并且达到目标后做的事情
    cyclicBarrier.await();//到达栅栏,让线程等待,等到有足够多到达栅栏的任务才会继续往下走。栅栏是循环的。
简单示例:https://blog.csdn.net/xiaoluo5238/article/details/104382801

多线程队列

队列分为 阻塞队列和非阻塞队列两种,阻塞队列里面又有很多很有趣的衍生。

Queue 基本方法如下:
    add();//如果队列已满,会抛出错误
    offer();//相当于add,如果队列已满,返回false
    remove();//删除第一个元素,集合为空时调用抛出异常
    poll();//删除第一个元素,集合为空时调用,返回null
    peek();//查询队列头部元素,空时null
    element();//查询队列头元素,空时报错
ConcurrentLinkedQueue 非阻塞队列
ConcurrentLinkedDeque 双端队列 多了从第一个和从最后一个的操作方法:的方法如:offerFirst offerLast pollFirst pollLast

BlockingQueue 阻塞队列
        比Queue新增了:
        put();//如果满了,就会等待
        take();//如果空了,就会等待
        blockingQueue.offer("123",10,TimeUnit.MINUTES);//添加,如果添加不成功,10分钟后,程序阻塞

    LinkedBlockingQueue 阻塞队列 列表
    ArrayBlockingQueue 阻塞队列 数组,要声明队列长度
    DelayQueue 延迟队列,执行定时任务,只能添加实现了 Delayed接口的对象
    LinkedTransferQueue  等待消费者消费才能进行生产,有消费者时它会直接找消费者,没有就阻塞
        transferQueue.transfer();  与add/offer 生产者生产,如果无消费者,它会阻塞
    SynchronousQueue 继承 TransferQueue,容量为0的队列,只能有put,只有消费者消费完之后才能进行put

        简单示例:https://blog.csdn.net/xiaoluo5238/article/details/104374753

多线程线程池

Executor 线程的执行
ExecutorService 执行任务的服务
    submit();//可以有返回值,可以传 Runnable/Callable 任务
    execute();//执行任务方法,无返回值。可以传Runnable任务
    shutdown();//关闭,会等所有线程都跑完后关闭线程池
Callable 是线程来调用的,有返回值的
Runnable 线程来调用,没有返回值
Executors 操作Executor的工具类,里面有很多静态方法(类比 Arrays是Array的工具类)
ThreadPool 线程池 线程池内的线程是循环使用的,线程不会消失
        //固定个数线程池
        ExecutorService fixThreadPool = Executors.newFixedThreadPool(5);
        //弹性线程 60秒线程不执行任务 自动消失 ,无线程上限数量
        ExecutorService cacheThreadPool = Executors.newCachedThreadPool();
        //每次只执行一个线程,线程前后执行
        ExecutorService singleThread = Executors.newSingleThreadExecutor();
        //定时执行
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4);
        //利用所有运行的处理器数目来创建一个工作窃取的线程池 ,这个work下所有的任务执行完了,会偷其它work下的任务
        ExecutorService work = Executors.newWorkStealingPool();

自定义线程池:
ThreadPoolExecutor(int corePoolSize,    //主线程数量
                              int maximumPoolSize,//最大线程数量
                              long keepAliveTime,//当线程超过最大线程数量时,超过线程的持续时间
                              TimeUnit unit,//时间单位
                              BlockingQueue<Runnable> workQueue)//阻塞队列

Future 模式(使用线程池):https://blog.csdn.net/xiaoluo5238/article/details/81975710

线程池的使用:https://blog.csdn.net/xiaoluo5238/article/details/81976677 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值