Java多线程技能
- 线程的启动
- 如何使线程停止
- 如何使线程暂停
- 线程的优先级
- 线程安全相关的问题
进程:进程是操作系统结构的基础,是一次程序的执行,是一个程序及其数据结构在处理机上顺序执行时所发生的活动,是程序在一个数据集合上运行的过程。它是系统进行资源分配和调度的基本单位。
线程:线程可以理解成进程中独立运行的一个子任务。使用多线程技术能够大幅提高CPU的利用效率。
实现多线程的方式主要有两种,一种是继承Thread类并重写Run方法,一种是实现Runnable接口并重写Run方法。
public class Thread implements Runnable
从上面源码可以看出,Thread类实现了Runnable接口,他们之间是多态关系,使用Thread类实现多线程时,最大的限制在于Java语言类是单根继承,所以为了实现多继承关系,可以通过实现Runnable接口的方式。
synchronized 关键字:
在run方法前加入synchronized关键字,是多线程在执行run方法时,以排队的方式进行处理。synchronized可以在任意变量或者方法上加锁,加锁的这段代码称为“互斥区”或“临界区”。
Thread方法
- currentThread()方法:返回代码段正在被哪个线程调用的信息,返回调用线程的名称。
- isAlive()方法:判断当前的线程是否处于活动的状态。活动状态:就是线程已经启动并且尚未终止,线程正处于正在运行或者准备开始运行的状态。
- sleep()方法:在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。
- getId()方法:取得线程的唯一标识。
停止线程
停止线程就是在线程处理完任务之前停掉正在做的操作,也就是放弃当前的操作。停止线程之前要做好防范措施,以达到预期的效果。停止线程可以使用Thread.stop()方法,但是它是不安全的,而且是已经废弃的方法(deprecated),大多数停止线程可以使用Thread.interrupt()方法,并且加入一些判断语句共同完成线程的停止。
在Java中有三种方法终止线程:
- 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止;
- 使用stop强制终止线程,但不推荐使用;
- 使用interrupt方法终止线程。
暂停线程
在Java多线程中,可以使用suspend()暂停线程,使用resume()方法恢复线程的执行,暂停线程意味着此线程还可以恢复运行。
使用suspend()和resume()方法存在缺陷,一是容易造成公共的同步对象的独占,导致其他线程无法访问公共同步对象,另一缺陷是容易因为线程的暂停而导致数据不同步的情况。
yield方法
yield()方法的作用是放弃当前CPU资源,将它让给其他的任务器占用CPU执行时间。但放弃的时间不确定,有可能刚放弃又被分配到时间片。
线程的优先级
在操作系统中,线程可以划分优先级,优先级较高的线程得到的CPU资源比较多。在Java中可以使用setPriority()方法设置线程的优先级。
线程的优先级分为1~10这十个等级。JDK中使用三个常量来预置定义优先级的值:
public final static int MIN_PRIORITY = 1
public final static int NORM_PRIORITY = 5
public final static int MAX_PRIORITY = 10
在java中,线程的优先级具有继承性,比如A线程启动B线程,则B线程具有和A相同的优先级。
不要把线程的优先级与运行结果的顺序作为衡量的标准,优先级高的线程并不一定每次都先执行完run()方法中的任务,也就是说,线程的优先级与打印顺序无关,CPU会尽量将执行资源让给优先级高的线程,但只是尽量,不是一定。
守护线程
在Java线程中有两种线程,一种是用户线程,另一种是守护线程。通俗的理解“守护线程”:任何一个守护线程都是JVM中非守护线程的保姆,只要当前JVM存在任何一个非守护线程,守护线程就会一直工作,指导JVM中最后一个非守护线程结束时,守护线程才会随着JVM一同结束工作。守护线程最典型的例子就是GC(垃圾回收器),当JVM没有执行的非守护线程时,垃圾回收线程也会自动销毁。