并发一(基本概念及理论准备)

写在前面:

多线程并发等知识点涉及面广,延伸度大,理论加源码的方式整理关于线程的部分基础知识,其他更多的更深的知识会在后面一一学习和整理,先学习基础,再延伸。

目录

一、线程与进程

二、线程实现

继承 Thread

实现Runnable

实现Callable&Future

三、线程生命周期及状态转换

新建

可运行

运行

阻塞

等待

超时等待

终止           

 

四、常见操作方法分析

Thread.sleep(long millis)

Thread.yield()

t.join()/t.join(long millis)

obj.wait()

obj.notify()

五、线程池

六、常见并发容器

ConcurrentHashMap

其他并发容器

队列

七、线程安全



一、线程与进程

进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,是系统进行资源分配和调度的一个独立单位,是程序运行的最小单元。

线程是指进程中的一个执行流程,没有自己的内存空间,是cpu运行和分派的最小单元。

在Java中,每次程序运行至少启动2个线程:一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个JVM实际上就是在操作系统中启动了一个进程。

二、线程实现

继承 Thread

由于java是单继承,所以基本不用这种实现方式

实现Runnable

接口,重写run()

实现Callable&Future

待续

三、线程生命周期及状态转换

新建

new                【来到体育场 】

可运行

runnable         【进入备跑区】

线程对象创建后,其他线程调用了该线程的start方法,进入线程池等待被调度选中,获取cpu使用权。当前线程sleep()方法结束,其他线程join()结束,等待用户输入完毕,某个线程拿到对象锁,这些线程也将进入可运行状态。当前线程时间片用完了,调用当前线程的yield()方法,当前线程进入可运行状态。锁池里的线程拿到对象锁后,进入可运行状态。

运行

running           【起跑】 

runnable状态下获得了cpu时间片(timeslice),执行程序。

阻塞

blocked           【停下去做点啥】     

线程因为某些原因放弃了cpu使用权,让出了cpu timeslice,暂停运行。直到线程重新进入runnable。

所谓阻塞状态是正在运行的线程没有运行结束,暂时让出CPU,这时其他处于就绪状态的线程就可以获得CPU时间,进入运行状态。

blocked分三种:
等待阻塞 wait()方法执行,进入等待队列(waitting queue)
同步阻塞 running的线程在获取对象的同步锁时,若该同步锁被别的线程占用,JVM会把它放到锁池(lock pool)中,等拿到锁之后才会进入可运行
其他阻塞 Thread.sleep(long ms)                                               睡上五分钟,醒来再进线程池
                t.join()                                                                        跑着跑着突然被插队,你不得不停下
               发出IO请求时,jvm会把该线程置为阻塞状态。         跑着跑着,你去看了看文件,所以得停下
当           sleep()状态超时                                                          睡醒了
               join()等待线程终止或者超时                                       插队的人走了或挂了
               或者I/O处理完毕时                                                     文件看完了

线程重新转入可运行(runnable)状态。

等待

waiting             【等着,别人叫再跑】

处于这种状态的线程不会被分配CPU执行时间,它们要等待被显式地唤醒,否则会处于无限期等待的状态。

超时等待

time waiting     【等着,过了等待时间就不等了】

处于这种状态的线程不会被分配CPU执行时间,不过无须无限期等待被其他线程显示地唤醒,在达到一定时间后它们会自动唤醒。

终止           

terminated       【跑完或者意外退场】

run()、main()执行结束,或因异常退出run()方法,结束该线程生命周期,死亡的不可复生。

 

四、常见操作方法分析

Thread.sleep(long millis)

一定是当前线程调用此方法,当前线程进入阻塞,但不释放对象锁,millis后线程自动苏醒进入可运行状态。作用:给其它线程执行机会的最佳方式。

Thread.yield()

一定是当前线程调用此方法,当前线程放弃获取的cpu时间片,由运行状态变会可运行状态,让OS再次选择线程。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。

t.join()/t.join(long millis)

当前线程里调用其它线程1的join方法,当前线程阻塞,但不释放对象锁,直到线程1执行完毕或者millis时间到,当前线程进入可运行状态。

obj.wait()

当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列。依靠notify()/notifyAll()唤醒或者wait(long timeout)timeout时间到自动唤醒。

obj.notify()

唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。
 

五、线程池

ThreadPoolExecutor extends Executor

六、常见并发容器

ConcurrentHashMap

待续

其他并发容器

待续

队列

同步队列

当前线程想调用对象A的同步方法时,发现对象A的锁被别的线程占有,此时当前线程进入同步队列。简言之,同步队列里面放的都是想争夺对象锁的线程。同步队列是在同步的环境下才有的概念,一个对象对应一个同步队列。

锁池队列

锁池里面放的都是想争夺对象锁的线程。当一个线程1被另外一个线程2唤醒时,1线程进入锁池状态,去争夺对象锁。

锁池是在同步的环境下才有的概念,一个对象对应一个锁池。

等待队列

        待续

七、线程安全

定义:CPU的使用权抢占和资源的共享发生了冲突

猜你喜欢

转载自blog.csdn.net/qq_36766417/article/details/109210369
今日推荐