java多线程编程核心技术】-- 第一章:java多线程技能
【java多线程编程核心技术】-- 第一章:java多线程技能
第一章总结
本章主要介绍了Thread类API的基本功能,使用这些API的的过程当中会出现一些意想不到的情况,学习和掌握一些常用情况,就掌握了多线程开发的命脉与习性,是学习多线程更深层知识的基础。
第一章知识点
基本概念
进程:是操作系统结构的基础,是一次程序的执行,是一个程序及其数据在处理机上的顺序执行时所发生的活动,也是系统进行资源分配和调度的一个独立单位。
线程:线程可以理解为在进程中独立运行的子任务。比如QQ.exe运行时会有很多子任务在同时运行,如视频线程、下载文件线程等,多线程的优点就是可以最大限度的利用CPU的空闲时间来处理其它任务,CPU在不同的任务之间的切换速度非常快,所以给使用者的感受就是这些任务似乎是在同时运行的。
如何使用多线程
- 继承Thread类
由于java单继承的局限性,所以通常用实现Runnable接口的方使用多线程 - 实现Runnable接口
实现Runnable接口,将Runnable对象传入Thread对象中调用start()方法启动线程
currentThread()方法
currentThread()方法返回代码段正在被哪个线程调用
public class MyThread extends Thread {
public MyThread(){
system.out.println(Thread.currentThread().getName()); //结果为main
}
public void run(){
system.out.println(Thread.currentThread().getName()); //结果为Thread-0
}
}
public static void main(String args[]){
system.out.println(Thread.currentThread().getName());//结果为main
MyThread myThread = new MyThread();
myThread.start();
}
isAlive()方法
方法返回true或者false,判断当前的线程是否处于活动状态,活动状态就是指线程已经启动并且尚未终止。线程处于正在运行或准备开始运行的状态,就认为线程是“存活”的。在启动线程之前都是false。
sleep()方法
Thread类中的静态方法sleep(),当一个执行中的线程调用了Thread的sleep()方法后(哪个线程调用了Thread.sleep()方法哪个线程就处于睡眠状态),调用线程会暂时让出时间的执行权,这期间不参与cpu的调度,但是该线程持有的锁是不让出的。时间到了会正常返回,线程处于就绪状态,然后等待cpu的调度,获取到cpu资源后又会处于运行状态。
getId()方法
Thread类中的静态方法,该方法的作用是取得线程的唯一标识。
Thread.currentThread().getId(); //在main方法中执行时返回1
停止线程
停止线程意味着在线程执行完任务之前停掉当前正在执行的操作,一定需要做好防范措施。Thread.stop()方法是不安全的方法,而且已经被弃用了;现在使用的方法多是使用Thread.interrupt()方法,这个方法不会马上终止一个正在执行的线程,还需要加入一个判断才能完成线程的停止。
java中主要有三种方式停止线程
- 使用退出标识,使线程正常退出
- 使用stop、suspend、resume方法都是过期作废的方法,使用它们可能会造成预想不到的结果
- 使用interrupt方法中断线程
interrupted()和isInterrupted()方法区别
interrupted():,Thread类的静态方法,测试当前线程是否已经中断,当前线程是指运行this.interrupted()方法的线程,同时该方法也有状态清除的功能
例子一:验证测试的是当前线程
public static void main(){
MyThread myThread = new MyThread();
thread.start();
Thread.sleep(1000);
system.out.println(myThread.interrupted());//结果为false
system.out.println(myThread.interrupted());//结果为false
//说明了interrupted()方法是测试当前线程是否已经中断,当前线程是main线程,main线程从未中断过
//该方法也具有清除线程中断状态的功能,所以连续两次调用都会返回false
}
例子二:验证具有状态清除功能
public static void main(){
Thread.currentThread().interrupt();
system.out.println(Thread.interrupted());//结果为true
system.out.println(Thread.interrupted());//结果为false
//该方法也具有清除线程中断状态的功能,第一次调用会清除线程的中断状态
//所以第二次调用的时候会返回false
}
isInterrupted():不是Thread类的静态方法,测试线程Thread对象是否已经中断,不会将中断状态清除为false。
例子:
public static void main(){
MyThread myThread = new MyThread();
thread.start();
Thread.sleep(1000);
system.out.println(myThread.isInterrupted());//结果为true
system.out.println(myThread.isInterrupted());//结果为true
//说明了isInterrupted()方法是测试线程Thread对象是否已经中断,当前线程是main线程,main线程从未中断过
}
线程在沉睡中停止将会抛出异常
例子:
public class MyThread extends Thread {
public void run(){
try {
Thread.sleeep(200000);
}catch(InterruptedException e){
system.out.println("在沉睡中停止了," + this.isInterrupted());
//结果将打印出来,sleep状态下停止停止某个线程,也会清除线程中断状态,打印出false
e.printStackTrace();
}
}
}
public static void main(String args[]){
MyThread myThread = new MyThread();
myThread.start();
Thread.sleep(200); //main线程睡眠,容易使MyThread线程获取CPU执行
thread.interrupt();
}
暂停线程
暂停线程意味着此线程还可以恢复运行,在java多线程中,可以使用suspend()方法暂停线程,使用resume()方法恢复线程的执行。
suspend()方法是过期作废的方法,现在也不会使用此方法了。
yield()方法
yield()方法的作用是放弃当前的CPU资源,将它交给其他的任务去占用CPU的执行时间,调用该方法之后线程又会处于就绪状态,参与到争夺CPU的竞争当中。
线程的优先级
线程可以划分为优先级,优先级较高的线程得到CPU的资源较多,设置线程优先级有助于帮“线程规划器”确定下一次选择哪一个线程优先执行打,但是这也不是绝对的,实际的还是要看CPU的执行情况。设置优先级使用setPriority()方法,该方法源码如下:
线程的优先等级分为1–10这10个等级,JDK常使用如下三个常量来预置定义优先级的值,代码如下
线程优先级还具有继承特性
比如A线程启动B线程,则B线程的优先级和A线程是一样的。
守护线程
在java线程中有两种线程,一种是用户线程,一种是守护线程。
守护线程是一种特殊的线程,当进程中不存在非守护线程时,则守护线程自动销毁。典型的守护线程就是垃圾回收线程,通过调用thread.setDaemon(true) 把thread设置成后台线程。