线程相关点滴积累(一)

1.实现线程的两种方式:

  1>继承Thread类;

  2>实现Runnable接口(ps:直接调用run方法就是普通方法调用;调用start才实现多线程)

2.Thread和Runnable异同:

  1>Thread中的run方法调用的其实是Runnable的run方法,这种操作模式即代理模式

  2>一个类继承Thread不适合资源共享,但如果实现了Runnable接口,则很容易实现资源共享

  3>Runnable更适合多个相同的程序代码的线程去处理同一个资源

  4>Runnable可避免java中的单继承限制

  5>Runnable增加程序健壮性,代码可被多线程共享,代码和数据独立

3.java中创建进程:1>Runtime.exec() ;2>ProcessBuilder.start()

4.

  1>sleep使线程睡眠,交出CPU,让CPU执行其他任务,不会释放锁;

  2>yield交出CPU,和sleep相似,但其不能控制交出CPU的时间,另外yield只能让拥有相同优先级的线程有获取CPU执行时间的机会,不会释放锁;

  3>子线程中join调用,则主线程会等待子线程执行完毕,如调用有参数的,则等待指定时间

  4>interrupt用于中断线程,但是它只会将线程的状态位置为"中断"状态,不会停止线程,如想终止,可在调用interrupt后,抛出异常new InterruptedException。如果当前线程处于sleep状态,调用此参数,会抛异常InterruptedException,清除停止状态值,将其变为false。Interrupt和isInterrupted都用于判断线程是否处于中断状态,interrupt作用于当前线程;isInterrupted作用于调用该方法的对象对应线程,这两个方法最终都调用isInterrupted(参数),只不过参数依次是true、false。interrupted代表返回状态位后,将状态标志置为false;isInterrupted则直接返回状态位。简言之:只有当前线程可清除自己状态位(interrupted)。

  5>wait方法会让线程进入阻塞状态,同时释放线程占有的锁,并交出CPU执行权限

5.synchronized修饰获取的是对象锁

6.synchronized和lock区别

  1>Lock是接口,而synchronizedjava内置关键字

   2>Synchronized发生异常会自动释放锁;而lock只有在显式调用unlock时才释放

   3>Lock可让等待的线程响应中断;而synchronized会一直等待

  4>Lock可通过tryLock看是否成功获取锁,而synchronized不成

  5>单线程时,两者性能差距不大,当资源竞争激烈时,lock性能优于synchronized

7.悲观锁和乐观锁区别:

  1>悲观锁是每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁

  2>乐观锁是每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,例如redis事务中的watcher监听。

8.公平锁即以请求锁的顺序来获取锁;非公平锁不会理睬线程等待时间。synchronized是非公平锁,ReentrantLock和ReentrantReadWriteLock默认为非公平锁,可设置为公平锁

9.变量用volatile修饰后,汇编代码中可以看到多了一个lock前缀指令,它相当于一个内存栅栏。它能保证读在写之后:因为主存数据共享,各个线程都有自己的工作缓存,运算时都是将主存数据复制到自己的工作缓存,volitile修饰后,保证该变量立刻从工作缓存刷回主存,并且cpu总线会发出信号让其他工作缓存中缓存行失效,从主存获取。

volatile能禁止指令重排序。

volatile能保证可见性,可用做状态变量。

10.copyOnWriteArrayList:插入元素时候,将原集合复制一个到临时集合中(加锁),向临时集合中插入,原集合只负责读,copy-on-write,读写分离提高读效率但占内存,同时存在数据一致性问题,他只能保证最终的数据一致性

11.concurrentHashMap:N个Segment,每个Segment对应一个HashEntry[](一个hashEntry是一个链表结构的元素),即ConcurrentHashMap定位一个元素进行两次Hash,第一次定位Segment,第二次定位元素所在链表头,读耗时正常,但写只需对相应Segment加锁。并发能力大大提高

12.为何用线程池:

  1>没有线程池可能造成系统创建大量线程导致内存耗尽及其过度切换

  2>减少在创建和销毁线程上所花时间及系统资源开销

13.线程池的实现原理:一个线程池包含四个基本组成部分:

  1>线程池管理器:用于创建并管理线程池,包括:创建、销毁、添加新任务

  2>工作线程:线程池中线程,在没有任务时处于等待状态,可以循环的执行任

  3>任务接口:每个任务必须实现的接口,供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等

  4>任务队列:用于存放没有处理的任务,提供一种缓存机制

14线程池处理任务策略:

  1>如果当前线程池中的线程数目小于corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务;

  2>如果当前线程池中的线程数目>=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若添加失败(一般来说是任务缓存队列已满),则会尝试创建新的线程去执行这个任务;

  3>果当前线程池中的线程数目达到maximumPoolSize,则会采取任务拒绝策略进行处理;

  4>如果线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止,直至线程池中的线程数目不大于corePoolSize;如果允许为核心池中的线程设置存活时间,那么核心池中的线程空闲时间超过keepAliveTime,线程也会被终止

15.任务缓存队列及排队策略

workQueue的类型为BlockingQueue<Runnable>,通常可以取下面三种类型:

  1>ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小;

  2>LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE

  3>synchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务

16.拒绝任务时的四种策略

ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。

ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。

ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)

ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

17.线程池的类继承结构:Executor接口(execute)—ExecutorService接口(submit、invokeAll、shutDown等)--AbstractExecutorService抽象类(实现接口中方法)--ThreadPoolExecutor继承抽象类,其中execute用于提交任务给线程池;submit提交任务(用execute)还可以用Future获取结果并返回

18.默认需提交任务才创建线程,在实际中如果需要线程池创建之后立即创建线程,可以通过以下两个方法办到:

1>prestartCoreThread():初始化一个核心线程;

2>prestartAllCoreThreads():初始化所有核心线程

19.java doc中建议创建线程池的方法:

  1>Executors.newCachedThreadPool()创建缓冲池,容量最大是Integer.MAX_VALUE,队列用synchronousQueue,每次来创建

  2>Execcutors.newSingleThread()创建线程池,容量为1

  3>Executors.newFixedThreadPool()创建固定容量的线程池

<span style="font-family:Microsoft YaHei;font-size:18px;">public static ExecutorService newFixedThreadPool(int nThreads) {

    return new ThreadPoolExecutor(nThreads, nThreads,

                                  0L, TimeUnit.MILLISECONDS,

                                  new LinkedBlockingQueue<Runnable>());

}

public static ExecutorService newSingleThreadExecutor() {

    return new FinalizableDelegatedExecutorService

        (new ThreadPoolExecutor(1, 1,

                                0L, TimeUnit.MILLISECONDS,

                                new LinkedBlockingQueue<Runnable>()));

}

public static ExecutorService newCachedThreadPool() {

    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,

                                  60L, TimeUnit.SECONDS,

                                  new SynchronousQueue<Runnable>());

}</span>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值