综述
多线程是非常重要的内容,同时又非常深入,这里对以前了解的内容做了一下总结,后续有机会还要继续深入的学习。
进程和线程
- 进程
- 进程有独立的地址空间,占据资源
- 任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。
- 线程
- 线程只是一个进程中的不同执行路径,线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间。
- 一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。进程中一定要有线程。
- 开启多线程,是为了同时运行多个代码,每个线程都有自己的运行的内容
进程状态
就绪
一个新创建的线程并不自动开始运行,要执行线程,必须调用线程的start()方法。当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态运行
当线程获得CPU时间后,它才进入运行状态,真正开始执行run()方法等待
所谓阻塞状态是正在运行的线程没有运行结束,暂时让出CPU,这时其他处于就绪状态的线程就可以获得CPU时间,进入运行状态。
信号量机和互斥锁
互斥量用于线程的互斥。
信号量用于线程的同步。
java多线程
创建
创建线程的目的是为了开启一条执行路径,去运行指定代码和其他代码同时运行。run方法里就是要做的事情。
自定义的线程都放在run方法中。
java中创建线程有两种方法,继承Thread类和实现Runnable接口
- 继承Thread类
1 将类声明成Thread类的子类
class demo extends Thread
2 在子类中重写run方法,run方法封装要进行的操作。
public void run(){
}
3 对象调用start方法开启线程
d1.start()
- 实现Runnable接口
1 将类定义为实现Runnable接口
class demo2 implements Runnable
2 在子类中重写run方法,run方法封装要进行的操作。
public void run(){
}
3 创建Thread对象,并把Runnable接口的子类对象作为Thread的参数传递进去。
Thread t1 = new Thread(new Demo1());
4 调用start方法开启线程
t1.start()
一般推荐使用实现Runnable接口的方法,实现Runnable接口的好处:
- 将线程的任务,从线程的子类中分离出来,进行了单独的封装
- 避免了java单继承的局限性。
线程启动
run
run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。
run方法里面封装线程任务,调用Runnable方法不能实现多线程的功能,只是执行一个普通的方法start
用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到spu时间片,就开始执行run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。