一、什么是进程?
进程就是处于执行期的程序。但进程并不仅仅是一段可执行的代码。通常进程还要包含其它资源,像进程标识符,打开的文件,接收到的信号,处理器状态,所分配的内存等信息。实际上,进程就是正在执行程序代码的实时结果,内核需要有效而又透明地管理所有的细节,所以一个进程需要维护非常多的信息。所以总的来说,进程就是处于执行期的程序以及相关资源信息的总称。
二、什么是线程?
线程是程序中的一个执行流,每个线程都有自己的专有的寄存器(栈指针,程序计数器等),(线程在运行的时候,代码在运行时,是通过程序计数器不断执行下一条指令。真正指令运算等操作是通过控制操作栈的操作数入栈和出栈,将操作数在局部变量表和操作栈之间转移。)但代码区是共享的,即不同的线程可以执行同样的函数,同一个进程中的所有线程共享该进程的所有资源。
线程从Linux角度来看就是task_struct结构体,是一段可执行的代码,CPU调度的最小单位
三、进程(线程)的特点小结:
进程的特点:可以同时存在多个进程,这些进程会交替执行,且切换频率高,每次切换到某个进程时,该进程运行的时间比较随机。
进程是若干个线程的集合,当进程运行时,真正运行的是进程中的线程。
每个正在执行的进程中,都至少存在1个正在执行的线程。
每个进程中,可以存在若干个线程。
线程具有以上提到的进程的所有特征。
线程可以理解是轻量级的进程。
每个进程启动时,会默认开启1个线程,该线程通常称之为“主线程”。
开发者可以在程序中自由的创建新的线程,并启动,这些新的线程通常称之为“子线程”,或者“工作线程”。
三、什么是多线程?
多线程就是一个程序中可以同时运行多个不同的线程来执行不同的任务,也就说允许单个程序创建多个并行执行的线程来完成各自的任务。
四、如何创建线程
两种方式创建线程
1.继承Thread类
1)自定义类,继承自java.lang.Thread类
2)在自定义类中重写public void run()方法
3)当需要启动线程时候,创建自定义类的对象,并调用该对象的start()方法
2.实现Runnable接口
1)自定义类,实现java.lang.Runnable接口
2)在自定义类中重写public void run()方法
3)当需要启动线程时候,创建自定义类的对象,然后创建Thread类对象,在创建
Thread类对象时,将自定义类对象作为构造方法的参数,最后,调用Thread类对象
的start()方法
五、什么时候使用多线程?为什么要使用多线程?
耗时操作,需要同时做多个事的时候用线程
主线程不能做耗时操作,会出现ANR异常。(ANR:Application Not Responding:应用程序无响应
ANR是由于主线程执行任务消耗时间过长导致的。)
所以需要把耗时的操作写在子线程里。
多线程可以提高CPU利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其他的线程而不是等待。这样就大大提高了程序的效率。
六、线程的生命周期
线程的生命周期开始于对象被创建的时候,结束于线程被终止或完成执行时。
未启动状态:当线程被创建但是start()方法没有调用的时候,该线程是未启动状态,可以运行状态。具体的执行时间由CPU决定。
就绪状态:已经调用了start()方法,等待CPU周期时的状态。
运行状态:CPU调度之后,就会是运行状态。
不可运行状态:已经调用Sleep()方法,已经调用wait()方法,通过I/O操作阻塞。这几种情况下线程是不可运行的。
死亡状态:当线程已完成执行或已经终止时的状态。
七、线程池
线程的创建和销毁需要消耗一定的开销,过多的使用线程会造成内存资源的浪费,处于对性能的考虑,引入了线程池的概念。线程池维护一个请求队列,线程池的代码从队列提取任务,然后委派给线程池的一个线程执行。线程执行完不会被立即销毁,这样既可以在后台执行任务,又可以减少线程创建和销毁所带来的开销。线程池线程默认为后台线程。
线程池自动管理线程的创建和销毁。
八、Sleep ()、suspend ()和 wait ()之间有什么区别?
Thread.sleep ()使当前线程在指定的时间处于“非运行”(Not Runnable)状态。线程一直持有对象的监视器。比如一个线程当前在一个同步块或同步方法中,其它线程不能进入该块或方法中。如果另一线程调用了 interrupt ()方法,它将唤醒那个“睡眠的”线程。
注意:sleep ()是一个静态方法。这意味着只对当前线程有效,一个常见的错误是调用t.sleep (),(这里的t是一个不同于当前线程的线程)。即便是执行t.sleep (),也是当前线程进入睡眠,而不是t线程。t.suspend ()是过时的方法,使用 suspend ()导致线程进入停滞状态,该线程会一直持有对象的监视器,suspend ()容易引起死锁问题。
object.wait ()使当前线程出于“不可运行”状态,和 sleep ()不同的是 wait 是 object 的方法而不是 thread。调用 object.wait ()时,线程先要获取这个对象的对象锁,当前线程必须在锁对象保持同步,把当前线程添加到等待队列中,随后另一线程可以同步同一个对象锁来调用 object.notify (),这样将唤醒原来等待中的线程,然后释放该锁。基本上 wait ()/notify ()与 sleep ()/interrupt ()类似,只是前者需要获取对象锁。
九、什么是死锁
死锁就是两个或两个以上的线程被无限的阻塞,线程之间相互等待所需资源。这种情况可能发生在当两个线程尝试获取其它资源的锁,而每个线程又陷入无限等待其它资源锁的释放,除非一个用户进程被终止。就 JavaAPI 而言,线程死锁可能发生在以下情况。
1)当两个线程相互调用 Thread.join ()
2)当两个线程使用嵌套的同步块,一个线程占用了另外一个线程必需的锁,互相等待时被阻塞就有可能出现死锁。
待续................................