Java线程

来源:互联网 发布:淘宝店铺过户流程图 编辑:程序博客网 时间:2024/06/05 07:57

Java线程同步

  1. volitile来标记变量的可见性,即任何访问变量之前,都会去主内存中刷新变量拷贝到工作内存中,但是由于java语句的非原子性,该关键字不一定能够保证,一致性。常常被用于一些单线程更新,而多个线程读取的场景,来标记状态,例如是否初始化成功等
  2. synchronized关键字通过monitorentor和monitorexit实现互斥锁来同步代码访问
  3. Java的线程模型:轻量级进程,用户线程,用户线程工作线程混合的模式
  4. 阻塞状态和等待状态的区别:阻塞是线程等待获取对象锁,而等待是线程等待被其他线程唤醒(notify/notifyAll)
  5. 锁类型: 互斥锁(synchronized,ReentrantLock),非阻塞同步(CAS操作),无同步方案(确保可重入代码)
  6. synchronized和ReentrantLock的区别:都是重量级的互斥锁,只是调用方式的不同,且ReentrantLock支持Condition, 公平锁等,所谓的公平锁是指当有多个线程同时等待获得锁的时候,ReentrantLock会使用一个内部实现的SynchronizedQueue来保证,先等待的线程优先获得锁,而synchronized无法保证这一点。JDK1.5以后两者的性能几乎没有多大差别,之前的JDK版本高并发下synchronized的吞吐量比ReentrantLock下降很多

高并发框架

  1. Distruptor: 用于实现高并发,低延迟的无锁队列。
    可选的等待策略,如果使用不当在并发量较大的时候会导致服务器CPU占用100%。

    • Disruptor默认的等待策略是BlockingWaitStrategy。这个策略的内部适用一个锁和条件变量来控制线程的执行和等待(Java基本的同步方法)。BlockingWaitStrategy是最慢的等待策略,但也是CPU使用率最低和最稳定的选项。然而,可以根据不同的部署环境调整选项以提高性能。

    • SleepingWaitStrategy和BlockingWaitStrategy一样, SpleepingWaitStrategy的CPU使用率也比较低。它的方式是循环等待并且在循环中间调用LockSupport.parkNanos(1)来睡眠,(在Linux系统上面睡眠时间60µs).然而,它的优点在于生产线程只需要计数,而不执行任何指令。并且没有条件变量的消耗。但是,事件对象从生产者到消费者传递的延迟变大了。SleepingWaitStrategy最好用在不需要低延迟,而且事件发布对于生产者的影响比较小的情况下。比如异步日志功能。

    • YieldingWaitStrategy是可以被用在低延迟系统中的两个策略之一,这种策略在减低系统延迟的同时也会增加CPU运算量。YieldingWaitStrategy策略会循环等待sequence增加到合适的值。循环中调用Thread.yield()允许其他准备好的线程执行。如果需要高性能而且事件消费者线程比逻辑内核少的时候,推荐使用YieldingWaitStrategy策略。例如:在开启超线程的时候。

    • BusySpinWaitStrategy是性能最高的等待策略,同时也是对部署环境要求最高的策略。这个性能最好用在事件处理线程比物理内核数目还要小的时候。例如:在禁用超线程技术的时候。

  2. Netty: 事件驱动的网络应用框架

    • Channel和具体的Connection对应,由一个ChannelEventLoop来处理,而EventLoop和一个Thread绑定,所以一个EventLoop中对数据流的处理都是顺序的,不存在线程问题。

    • ChannelEventLoop由ChannelEventLoopGroup管理

    • Serverbootstrap可以有两个ChannelEventLoopGroup, 分别对应ServerSocketChannel(接受客户端连接),SocketChannel(复杂数据的read/write操作)

    • Socket接收数据,然后经过一系列的ChannelHandler,最后再交给Socket/Transport发送出去,Server端和Client端是一样的。
      Writing to the channel directly causes the message to start from the tail of the ChannelPipeline where as writing to the context object causes the message to start from the next handler in the ChannelPipeline.

    • 在高并发环境中不要在ChannleHandler中阻塞IO,否则会引起性能的问题,因为如果一个ChannelHandler被阻塞, 会导致对应的EventLoop不能处理其他请求。对于可能阻塞ChannelHandler的请求,可以在添加Handler的时候,指定EventExecutorGroup,这样会启用一个EventExecutor来执行IO操作,从而释放掉EventLoop

1 0
原创粉丝点击