并发编程之线程

一、创建线程的方式

1.继承Thread类,重写该类的run()方法。

2.实现Runnable接口,并重写该接口的run()方法,该run()方法同样是线程执行体,创建Runnable实现类的实例,并以此实例作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象。接口 静态代理

3.使用Callable和Future接口创建线程。具体是创建Callable接口的实现类,并实现call()方法。并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建线程。有返回值和异常。JUC包

 二、线程的生命周期及五种基本状态

  2.1 线程生命周期:新建(new)、就绪(start/yield等)、运行(CPU run)、阻塞(sleep/join等)、死亡(stop/加flag)。

 2.2 Thread类和Object的方法

sleep暂停/yield礼让属于类方法;join插队属于对象方法。

  2.3 守护线程

    用户线程和守护线程(Daemon)。jvm的退出不用等待守护线程执行完成。例:垃圾回收线程。应用场景:jvm退出时,线程能够自动退出。

    设置守护线程:t.setDaemon(true)  验证守护线程:t.isDaemon.

  2.4 Hook(钩子)线程 

    jvm退出的时候,钩子线程就会被启动执行。

   Runtime.getRuntime().addShutdownHook(new CleanWorkThread());

  2.5 常用方法

  isAlive()、setName()、getName()、currentThread()类方法。

三、高并发

 3.1 并发:同一个对象多个线程同时操作。抢占资源

 3.2 线程同步(线程安全):队列与锁 Synchronized

 锁机制:锁住对象或Class对象。

 3.3 Synchronized方法和Synchronized块 线程安全

     synchronized 方法:public synchronized void test(){}。

  synchronized 块:synchronized (obj){}。 obj:同步监视器。粒度更小

       性能优化:临界值、double checking。

  3.4 并发容器

      concurrent包:CopyOnWriteArrayList

  3.5 死锁

      原因:相互不释放资源。

      避免:不要在同一个代码块中,同时持有多个对象锁。

 3.6 并发协作 线程协作

      3.6.1生产者消费者模式

       1) 线程通信

      3.6.2协作模型之管程法

        1)生产者 消费者 缓冲区

        2)Object类  wait() 释放锁,notify()/notifyall() 成对出现

      3.6.3协作模型之信号灯法

       1)生产者 消费者 标志位

 3.6 高级主题-定时调度

  java.util.Timer

       java.util.TimerTask

 3.7 任务定时调度框架-quartz

     Scheduler:调度器,控制所有的调度

     Trigger:触发条件,采用DSL模式

     JobDetail:需要处理的任务

   Job:执行逻辑

 3.8 重排序:Happen-Before

    重排序:编译器和CPU会尝试重排指令使得代码更快地允许。目前:提供性能

    数据依赖:编译器和处理器在重排序时,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。

3.9 volatile修饰

    当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,

    当有其他线程需要读取时,它会去内存中读取新值(JMM通过将工作内存的设为失效,以让其直接去读内存)。

    volatile变量的内存可见性是基于内存屏障实现的。

   1) java内存模型中的可见性、原子性和有序性。

       可见性:是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。Java中volatile、synchronized和final实现可见性。

  原子性:synchronized、lock、unlock保证原子性。

       有序性:volatile、synchronized保证线程之间操作的有序性。

   2) volatile保证线程间变量的可见性。不能保证原子性。

   3) 原理:内存屏障。通过内存屏障可以禁止特定类型处理器的重排序。

  4) volatile规则:如果一个线程对volatile变量读,另一个线程对该变量写,那么写操作一定发生在读操作之前。

3.10 dcl单例模式

    volatile保证线程间变量的可见性。不能保证原子性。

    1)构造器私有化-->避免外部new构造器

    2)提供私有的静态属性-->存储对象的地址

    3)提供公共的静态方法-->获取属性

3.11 ThreadLocal 线程的本地存储区域

    get/set/initialValue初始化方法。

    private static修饰

    InheritableThreadLocal:继承上下文环境的数据,拷贝一份给子线程。

3.12 可重入锁实现原理

    锁可以延续使用+计数器

    可重入锁:公平锁和不公平锁。公平锁:等待时间长的先获得锁。

    JUC包:ReentrantLock.

3.13 CAS原子操作 Compare and swap 比较并交换。

   悲观锁:synchronized关键字、lock接口。

   乐观锁:CAS:属于硬件级的操作(利用CPU的CAS指令),是乐观锁的一种实现。效率高

  JUC(java.util.concurrent)中AtomicXxx类:AtomicInteger.decrementAndGet()。

四、多线程小结

 4.1 推导lambda简化线程    拉姆达

 4.2 在并发编程中,比较常用的是使用synchronized关键字和Lock接口同步,或者volatile关键字,来确保多线程下的有序性。

   

原文地址:https://www.cnblogs.com/wenxiangchen/p/10955879.html