Java入门经典——多线程技术

写在前面

这篇随笔就简单记录一下《Java入门经典》第12章——“一心二用”的多线程技术中看到的一些知识点。

进程与线程

一个进程是一个包含自身执行地址的程序,通常将正在运行的程序成为进程。

一个进程内部可以执行多任务,将进程内部的任务成为线程。线程是进程中的实体,一个进程可以拥有多个线程。

说道线程与进程可以参考:

一个线程是进程中执行的一个流程,一个程序中可能同时进行多个不同的线程,每一个线程可以执行一小段时间,由于多个线程之间切换速度快,所以就好像是程序同时执行多件事情一样。

线程必须拥有父进程,系统没有为线程分配资源,他与进程中的其他线程共享该进程的系统资源。

所谓单线程,是一个程序内某个结构化的流程控制,有时候被称为“执行环境”或“轻量级程序”,它是由上而下的结构化程序。

创建线程

Java中,线程也是一种对象,目前有两种方法创建线程:

  1. 继承Thread类;
  2. 实现Runnable接口。

1.继承Thread类

Thread类是java.lang中的一个类,从这个类中实例化的对象代表线程。Thread类的两个常用的构造方法如下:

public Thread(String thread Name);
public Thread();
//OR
public class ThreadTest extends Thread{
    //...
}

完成线程真正功能的代码放在类的run()方法中,当一个类继承Thread类后,可以在该类中覆盖run()方法,将实现该线程功能的代码写入run()方法中,然后调用Thread类中的start()方法执行线程。

run()方法的格式如下:

public void run(){
    //...
}

如果start()方法调用一个已经启动的线程,系统会抛出Illegal Thread State Exception异常。

当执行一个线程程序时,会自动产生一个线程,主方法在该线程上运行,程序员负责启动自己的线程,代码如下:

public static void main(String[] args){
    new ThreadTest().start();
}

2.实现Runnable接口

由于Java不支持多继承,所以程序员要想实现继承其他类来实现线程使用,就可以通过Runnable接口来实现。代码如下:

public class Thread extends Object implements Runnable

线程的生命周期

线程具有生命周期,包含七种状态:

  1. 出生状态:用户在调用线程实例start()方法之前,线程处于出生状态。
  2. 就绪状态;用户调用start()方法之后,线程处于就绪状态。
  3. 运行状态;线程得到系统资源后进入运行状态。
  4. 等待状态;运行状态下的线程调用wait()方法后,会进入等待状态。等待状态中的线程需要通过notify()方法才能被唤醒,notifyAll()方法是将所有处于等待状态下的线程唤醒。
  5. 休眠状态;线程调用Thread类中的sleep()方法时,会进入休眠状态。
  6. 阻塞状态;如果一个线程在运行状态下,发出输入/输出请求,线程会进入阻塞状态。在等待输入/输出结束时,线程进入就绪状态。
  7. 死亡状态:线程的run()方法执行完毕时,线程进入死亡状态。

线程的优先级

Java中,线程有其优先级,范围是1~10,默认值为5.可以使用Thread类的setPriority()方法来设定线程的优先级。必须在1~10之间。

一般都会将线程放入无限循环内,然后设置跳出循环的条件。

线程的控制

线程的控制包括线程的启动、挂起、状态检查,以及如何正确结束线程,由于在程序中使用多线程,因此需要合理的安排线程的执行顺序,对线程进行相应的控制。

1.线程的启动

一个新的线程在创建后处于初始状态,实际上并没有立刻进入运行状态,而是处于就绪状态,当轮到这个线程执行时,即进入可执行状态,开始执行线程run()方法中的代码。

执行run()方法是通过调用Thread类中的start()方法来实现的。调用start()方法启动线程的run()方法不同于一般的调用方法,调用一般方法时,必须等到一般方法执行完毕才能返回,对于start()方法来说,调用线程的start()方法后,start()方法告诉系统该线程准备就绪并可以启动run()方法后就返回,并继续执行调用start()方法下面的语句,这是,run()方法可能还在运行,这样,线程的启动和运行并行进行,实现了多任务操作。

2.线程的挂起

线程的挂起操作实质上就是使线程进入非可执行状态。有以下几种情况使线程进入非可执行状态:

  1. 调用sleep()方法使线程进入休眠状态,线程在指定时间内不会运行;
  2. 调用join()方法使现场挂起,如果某个线程在另一个线程t上调用t.join(),这个线程将被挂起,直到线程t执行完毕。
  3. 调用wait()方法使线程挂起,直到线程得到了notify()、notifyAll()消息,线程才会进入可执行状态。
  4. 线程在等待某个输入/输出完成。

sleep()方法是一个使线程暂停一段执行时间的方法,该时间由给定的毫秒数决定。

当一个线程A,现在需要插入线程B,并要求线程B先执行完毕,而后再执行现场A,此时可以使用THread类中的join()方法完成。当某个线程使用join()方法加入到另一个线程时,另一个线程会等待该线程执行完毕再继续执行。

还可以使用wait()方法与notify()方法结合,第一种方式可以使用wait()按照系统给定时间挂起;第二种方式是wait()与notify()方法配合使用,让wait()方法无限等下去,直到线程接收到notify()或notifyAll()为止。

需要注意,wait(),notify()与notifyAll()方法都被声明为final类,无法重新定义。

3.线程的结束

线程的结束从run()方法的结尾处返回,自然消亡且不能再被运行。

猜你喜欢

转载自blog.csdn.net/zy2317878/article/details/80625640