(1)为了使CPU的时间利用率更高,就有了多进程和多线程机制。
进程是程序的一次执行,线程是进程中执行的一段程序片段
多进程:在操作系统中,能够同时运行多个任务(程序)
多线程:在同一个程序中有多个顺序同时执行
(2)在Java中,实现多线程的类是 Thread 类。
开发线程有两种方式:一种是直接继承Thread,另一种是实现Runable接口。
两者都需要重写 run 方法。
方式一:
class mythread extends Thread
{
public void run()
{
//线程所要执行的任务
}
}
创建线程对象:Thread mt1=new mythread();
Thread mt2=new mythread();
方式二:
class myrunnnable implements Runnable
{
public void run()
{
//线程所要执行的任务
}
}
创建对象:myrunnable mr=new myrunnable();
Thread t1=new Thread(mr);
Thread t2=new Thread(mr);
实现多个线程启动将执行完全相同的任务,共享相同的资源
(3)线程的状态:新建 、准备 、等待/阻塞 、运行和死亡状态。
这些状态可以转换的,线程的状态转换为:准备可以进入运行,运行也可以进入准备;运行还可以进入等待/阻塞;但是等待/阻塞不能进入运行,等待/阻塞可以进入准备状态。
- 新建:就是利用Thread的构造函数定义一个线程(new),从此,线程的生命开始了。该线程只是一个空对象,系统没有分配资源(线程处于new thread状态)
- 准备:当执行了Thread中的strat方法,启动线程,使得线程进入准备状态(可运行状态runnable),随时可以进入运行状态。系统为线程分配了除CPU外的所需资源。
- 运行:当操作系统的调度器把CPU分给了这个线程,这个线程就进入了运行状态,也就是执行我们在线程中定义的run方法里面的内容。
- 等待/阻塞 :
- 当一个线程的继续执行需要一个条件,但是该条件还不成熟,需要调度器来通知。而等待调度器发出通知的这段时间内,线程就进入了等待状态。
- 当一个线程访问一个资源的时候,这个资源正被另外的线程访问,而这个资源是加了锁的,之允许一个线程访问。这时候,线程就进入了阻塞状态。
- 死亡:当线程的run方法运行完之后,线程死亡,这是正常死亡;当线程方发生异常而没有捕获时,也会死亡,这是非正常死亡。
(4)线程的一些重要属性:
- 每个线程都有自己的优先级 。Java中的线程有10个优先级。但是结合操作系统来说,每个操作系统的线程优先级的数量各不相同。所以,Java提供了三个常量,分别是MIN_PRIORITY,NORM_PRIORITY,MAX_PRIORITY。
- 守护属性 :如果线程被标志为守护属性,那么这个线程就是守护线程 。守护线程不能阻止程序的退出,只要没有主线程,程序就结束,而不管守护线程的运行状态。所以,我们一般不在守护线程中做一些主要工作。
设置线程的守护属性函数为:setDaemon(true)
- 未捕获的异常处理器 。如果线程抛出的异常没有被捕获,线程就会死亡。这就意味着,在设计线程时,要重视捕获异常。但是,如果没有捕获异常,或者出现了一个异常不到的异常,是不是线程就马上死亡呢?当然不是。
线程有一个重要的属性,就是未捕获的异常处理器 。
使用这个方法设置:setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)