初识并发编程

2019-02-27  本文已影响0人  925781609

1. 并发与并行:

      1) 并发: 一段时间内能同时处理多个请求

      2) 并行: 多个CPU同时去执行

2. 什么时候应该使用多线程:

      1) 需要等待网络、I/O响应导致耗费大量的执行时间,而且对实时性要求也不高,可以采用异步线程的方式来减少阻塞

      2) 通过并行计算提高程序执行性能

3. 线程状态:

      1) new: 线程刚被创建,还没有调用start方法

      2) runnable: 获得锁正在执行(running)或准备执行(ready, 由于cpu切换走干别的了)

      3) blocked: 没获得到锁,被阻塞

      4) waiting:    已经获得锁、正在运行的线程,调用wait, join,park 进入等待, notify,upark从等待状态返回

      5) time_waiting: 超时等待,和waiting相比,多一个sleep进入超时等待,多一个超时时间到返回。 wait释放锁,sleep不释放锁

      6) terminated: 线程执行完毕

   ( 针对这个图稍微有一点疑问, 对于Object.wait(),线程会释放锁,那么从waiting状态返回时会先通过cas自选,如果额能获取锁进入runnable状态, 获取不到锁应该进入blocked状态 )

4. 线程的启动:

      start是native方法,最终告诉jvm调用run方法

5. 线程的停止:

      1) Thread过期的stop,resume, suppend API, 停止线程时,不会释放已经占有的资源,例如锁

      2) interrupt方法:

            i. 其他线程调用该线程的interrupt方法,设置该线程的中断标志位, 至于什么时候中断,由该线程决定

  可以通过isInterrupt判断中断标志位是否被配置,如果配置了将程序暂停

ii. 遇到低优先级的block状态时,比如object.wait(),object.sleep(),object.join()。

  interrupt通过 unpark 去唤醒出于waiting状态的线程,并设置中断标识。 wait/sleep/join会throw一个InterruptedException, 抛出异常后,会清除中断标志位

6. 线程安全性问题:

  1) JMM:

  i. 定义了共享内存系统中多线程程序读写操作行为的规范,来屏蔽各种硬件和操作系统的内存访问差异

  ii. 共享变量是指实例对象、静态字段、数组对象等存储在堆内存中的变量。而对于局部变量这类的,属于线程私有,不会被共享 。

  2) 线程安全性问题:

  i. 可见性:一个线程改变工作内存中的变量,另一个线程立刻可见

  ii. 原子性:多线程内自增某一个变量

  iii. 有序性:  编译器优化+ 指令重排序, 执行顺序和代码顺序不一致,前提是不影响单线程代码语义,却会影响多线程并发执行的正确性

7. 多线程间的通信:

  1) 共享内存:

  主内从存放共享变量、多个线程的工作内存会缓存共享变量, 线程对工作内存的修改会同步到主内存中(什么时候同步不一定,会引起可见性问题)

  2) 消息传递: wait/notify

8.Thread,Runnable,Callable:

  1)Runnable 和Callable是两个接口,分别有run和call两个方法, Runnable方法有返回值, Callable方法没有返回值

  2)Thread实现runnable, runnable通过Thread实现多线程,由一个runnable创建的多个Thread间会共享数据。

        Thread是对象, runnable接口, runnable可以解决多继承的问题

    i. Thread

  执行结果如下, 可以看到三个t1,t2,t3 三个线程各卖5张票,三个线程彼此独立

    线程t1卖第4张票

    线程t1卖第3张票

    线程t1卖第2张票

    线程t1卖第1张票

    线程t3卖第4张票

    线程t2卖第4张票

    线程t2卖第3张票

    线程t2卖第2张票

    线程t2卖第1张票

    线程t2卖第0张票

    线程t3卖第3张票

    线程t3卖第2张票

    线程t3卖第1张票

    线程t3卖第0张票

    线程t1卖第0张票

ii. Runable

    执行结果如下 ,可以看到Runnable中的count在多个线程中共享,并且出现并发问题:

    线程t1卖第3张票

    线程t2卖第2张票

    线程t2卖第0张票

    线程t3卖第3张票

    线程t1卖第1张票

    现在对为什么Runnable中的count能够在多线程中共享,首先看Thread中的源码,可以看到多个Thread中的target引用同一个Runnable对象,Thread的run方法,最终调用的就是同一个Runnable对象的run方法,所以Runnable中的数据会被共享

iii. Callable:

Callable 可以有返回结果,通过Future或者FutureTask来获得异步执行的结果, FutureTask扩展RunnableFuture, RunableFuture 扩展 Runnable和Future

使用示例如下:

    Callable+ Future 最终也是以Callable+FutureTask实现的, executorService.submit(myCallable)的源码如下:

相关源码:https://github.com/925781609/JavaCodeLibary/tree/master/src/main/java/com/liuil/codelibary/multithread

上一篇下一篇

猜你喜欢

热点阅读