------- android培训、java培训、期待与您交流! ----------
多线程(上)
本章重点掌握知识点:1、多线程的概念(上 )
2、线程创建的两种方式(上)
3、线程的生命周期及状态转换(上)
4、线程的调度(下)
5、线程的安全与同步(下)
6、多线程通信(下)
第一节:多线程的概念
学习多线程之前要知道两个概念:
★进程:
- 就是指当前正在运行的程序,如我们用QQ音乐听歌的时候,QQ音乐就是一个进程,
- 用QQ游戏斗地主的时候,QQ游戏就是一个进程,Java程序在启动时,就产生了一个进程。
★线程:
- 当我们知道了什么是进程后,就可以简单的理解为,每个进程在运行的时候都会
- 默认的创建一个或者多个线程,Java程序在启动时,就产生了一个进程,
- 该进程也会默认创建一个线程,在这个线程上运行main()方法中的代码。
- 学习了这两个概念后,我们知道,当一个Java程序在运行的时候都是按照调用代码的
- 顺序依次往下执行,没有出现两段代码交替着运行的情况,这样的程序叫做 单线程程序。
- 而如果希望程序中的代码交替运行时,则需要创建多个线程,这就是多线程程序。
第二节:线程创建的两种方式
★在java中提供了两种多线程的实现方式
- 第一种方式:继承java.lang包下的Thread类,覆盖并重写Thread类中run()方法,
- 在run()方法中实现运行在线程上的代码。
- 第二种方式:实现java.lang包下的Runnable接口,同样是在run()方法中实现运行
- 在线程上的代码。
★第一种方式:继承Thread类创建
package cn.itbasis;
/*
* 如果这个是单线程程序的话,在执行myThread.start();这句代码的时候会造成无限循环,
导致System.out.println("执行B方法");
* 这句输出语句不能执行,而现在创建了多线程后,就避免了这种情况,
使得这两个程序可以交替运行,这就是多线程的好处。
* 弊端:这种方式有局限性,因为java只支持单继承,一个类一旦继承了某个父类就无法再继承Thread,
所以还有另一种创建办法,实现
*/
public class Example01 {
public static void main(String[] args) {
//创建线程MyThread的线程对象
MyThread myThread = new MyThread();
//使用start()开启线程
myThread.start();
//main自己的一个无限循环,用于演示多线程
while(true){
System.out.println("执行B方法");
}
}
}
class MyThread extends Thread{
public void run(){
//用无限循环演示这个多线程
while(true){
System.out.println("执行A方法");
}
}
}
★ 第二种方式:实现Runnable类创建
package cn.itbasis;
/*
* 为了克服Thread类的单继承问题,一个类一旦继承了某个父类就无法再继承Thread,所以Thread类还提供另外一个构造方法,
* Thread(runnable target),runnable 是一个接口,它只有run()方法。
*/
public class Example02 {
public static void main(String[] args) {
//创建实例对象
MyThread myThread = new MyThread();
//创建线程对象
Thread thread = new Thread(myThread);
//开启线程
thread.start();
while(true){
System.out.println("执行B程序");
}
}
}
class MyThread implements Runnable{
//线程的代码段,当执行start()方法的时候,线程从这里开始执行
public void run(){
while(true){
System.out.println("执行A程序");
}
}
}
★两种方式的对比: 实现Runnable相对于继承Thread类来说,有以下好处
- 适合多个相同程序代码的线程去处理一个资源的情况(如火车票代售系统),
- 把线程同程序代码、数据有效的分离,很好的体现了面向对象的设计思想。
- 可以避免由于java的单线程带来的局限性。如一个已经继承了某一个类的子类
- 创建线程,由于一个子类不能同时继承两个父类,所以不能用继承Thread类的方式,
- 只能采用实现Runnable接口的方式。
第三节:线程的生命周期及状态转换
- 任何对象都有生命周期,线程也不例外,当Thread对象创建完毕后,
- 线程的生命周期开始,直到run()方法中的代码正常执行完毕,
- 或者线程抛出一个未捕获的异常(Exception)或者错误(Error)时,线程的生命周期就结束。
★注意:线程从阻塞状态只能进入就绪状态,而不能直接进入运行状态,
结束阻塞的线程需要重新等待系统的调度
- ◎当线程在试图获取某个对象的同步锁时,如果该锁被其他程序所持有,当前线程会进入
- 阻塞状态,只有在获取了其他线程所持有的锁后才能从阻塞状态转换成就绪状态。
- ◎当线程调用了一个阻塞式的IO方法时,线程会进入阻塞状态,
- 如果想进入就绪状态就必须等到这个阻塞的IO方法返回。
- ◎当线程调用了某个对象的wait()方法时,线程会进图阻塞状态,
- 如果想进入就绪状态就必须使用notify()方法唤醒该线程。
- ◎当线程调用了Thread的sleep(long millis)方法时,也会使线程进入阻塞状态,
- 在这种情况下只要等到线程睡眠时间到了以后,线程就会进入就绪状态。
- ◎当在一个线程中调用了另一个线程的join()方法时,会使当前线程进入阻塞状态,
- 在这种情况下只要等到新加入的线程运行结束后才会结束阻塞状态,进入就绪状态。