Java多线程的相关知识
线程、进程、程序的基本概念和联系
程序是包含指令和数据的文件,被存储在磁盘或其他数据存储设备中,则程序时静态的代码。
进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的 过程。比如说,打开一次word,编辑,最后关闭,这一整个过程就是一次进程。
线程是与进程相似的执行过程,但其是一个比进程更小的执行单位,一个进程在执行过程中可以产生多个线程。
二者的联系和区别:
线程与进程不同的是同类的多线程共享同一块内存和一组系统资源,所以系统在产生一个线程,或者在各个线程切换工作时,负担要不进程小。
线程和进程最大的不同在于基本上各进程是独立的,而线程则不一定,因为统一从另一个角度讲,进程输于操作系统的一部分,主要是痛磁盘内,可以同时执行一个以上的程序,而线程则是在同一程序内几乎同时执行一个以上的程序段。
线程的基本状态有
NEW:初始状态,线程被构建但还未调用Start()方法。
Runnable:运行状态,java线程将操作系统中的就绪和运行两种状态笼统地称作“运行中”。
BLOCKED:阻塞状态,表示线程阻塞于锁。
WAITING:等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程做出一些特定的动作(通知和中断)
TIME_WAITING:超时等待,该状态不同于WAITING,它是可以在指定的时间自行返回的。
TERMINATED:终止状态,表示当前线程已经执行完毕。
java线程状态变迁如图:
上图工作流程:
线程创建之后处于新建状态,调用Start()方法后,线程处于就绪状态,则可以开始运行。可运行状态的线程获得了CPU时间片(TIMESLICE)后处于运行状态。当线程执行完wait()方法后,线程进入WAITING等待状态。进入等待状态的线程需要串行其他线程的通知才能够返回到运行状态,而TIME_WAITING超时等待状态相当于在等待的基础上增加了超时限制,通过比如sleep(long millis)方法或者wait(long millis)方法可以将java的线程置于TIME_WAITING状态。当超时件到达后的Java线程将会返回到RUNNABLE状态。当线程调用同步方法时,在没有获取到锁的情况下,线程将会进入到BLOCKED(两次)状态。线程在执行Runnable的Run()方法之后将会进入到TERMINATED终止状态。
操作系统一藏在Java虚拟机JVM中的READY和RUNNABLE状态,他只能看到RUNNABLE状态,故Java系统一般将这两个状态统称为RUNNABLE运行状态
注意:Java程序每次运行时都要至少启动两个线程,一个就是主方法中的线程main(),也称为主线程,另一个则是垃圾收集线程(CG)
停止线程:
通过改变标志位类设置线程的停止
Runnable接口和Thread类的联系和区别
联系:
Thread类实际上时Runnable的子类,Thread类完成了比线程主体更多的操作,例如分配CPU资源,其类似的看做代理设计模式。
区别:
使用Thread类在操作多线程时无法达到资源共享的目的,而是用Runnable接口实现的多线程操作则可达到资源共享,这就是为什么在开发中Runnable接口被普遍的应用了。
Runnable接口相比于Thread类的优势
-
适合多个相同程序代码的线程去处理同一资源的情况,例如,多个售票点在同一个系统进行售票。
-
避免了由Java单继承特性带来的局限
-
增强了程序的健壮性(代码和数据相互独立),代码被多个线程共享。
多线程的同步和死锁
同步(Synchronized)是指多个操作在同一个时间段内只能有一个线程进行,其他线程要等待此线程完成之后才可以继续执行,主要解决了在多个时间段(存在延迟的情况)多个线程出现重复操作。一般资源共享时都需要加入同步,保证资源能运行的正确性。
死锁:一般情况下是指表示互相等待,是程序运行时出现的一种问题。注意:在一个线程中,在资源共享时是必须加入同步操作的,但是过多的同步操作一般就产生死锁。