概述
参考资料 《Java多线程编程核心技术》Java Multi-thread Programming 高洪岩 著
第一章:Java多线程技能
进程与线程的相关知识可以参考浅谈进程和线程
本章主要介绍Thread类的核心方法。
本章的关键技术点:
- 线程的启动
- 如何使线程暂停
- 如何使线程停止
- 线程的优先级
- 线程安全相关的问题
使用多线程的优点:提升系统的运行效率。
实现多线程的方式(两种)
(一)继承Thread类
//Thread类的定义
public class Thread implements Runnable {
//可以看出,Thread类实现了Runnable接口,它们之间具有多态关系。
该方法缺点:不支持多继承。
继承Thread类的多线程例子:
/**
* 自定义线程类MyThread.java,此类继承Thread,并且重写run方法。
* @author Administrator
*
*/
public class MyThread extends Thread {
@Override
public void run() {
super.run();
System.out.println("MyThread");
}
}
/**
* 运行类
* @author Administrator
*
*/
public class Run {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
System.out.println("运行结束!");
}
}
//运行结果为:
运行结束!
MyThread
从运行结果可以看出,代码的运行结果与代码执行顺序或调用顺序是无关的。即,线程的调用具有随机性。
(二)实现Runnable接口
如果想要创建的线程类已经有一个父类了,这时就不能再继承Thread类了(Java不支持多继承),我们可以使用实现Runnable接口的方法来应对这样的情况。
实现Runnable接口的多线程例子:
/**
* 实现Runnable接口的类MyRunnable
* @author Administrator
*
*/
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("运行中!");
}
}
/**
* 运行类
* @author Administrator
*
*/
public class Run {
public static void main(String[] args) {
Runnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
System.out.println("运行结束!");
}
}
//运行结果:
运行结束!
运行中!
Thread.java类也实现了Runnable接口,意味着构造方法Thread(Runnable target)不光可以传入Runnable接口的对象,也可以传入Thread类的对象,这样做完全可以将一个Thread对象中的run()方法交由其他的线程进行调用。
##currentThread()方法
**功能:**返回代码段正在被那个线程调用的信息。
public class MyThread extends Thread {
public MyThread() {
System.out.println("构造方法的打印:" + Thread.currentThread().getName());
}
@Override
public void run() {
System.out.println("run方法的打印:" + Thread.currentThread().getName());
}
}
/*
* 测试类1
*/
public class Run {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
//myThread.run();
}
}
//运行结果:
构造方法的打印:main
run方法的打印:Thread-0
/*
* 测试类2
*/
public class Run {
public static void main(String[] args) {
MyThread myThread = new MyThread();
//myThread.start();
myThread.run();
}
}
//运行结果:
构造方法的打印:main
run方法的打印:main
*说明:*打印出来的main是一个名称叫作main的线程在执行,跟代码中的main没有任何关系。
##isAlive()方法
**功能:**判断当前的线程是否处于活动状态。
**活动状态:**就是线程已经启动且尚未终止。线程处于正在运行或准备开始运行的状态,就认为线程是“存活”的。
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("run=" + this.isAlive());
}
}
/*
* 测试类
*/
public class Run {
public static void main(String[] args) {
MyThread myThread = new MyThread();
System.out.println("begin=" + myThread.isAlive());
myThread.start();
System.out.println("end=" + myThread.isAlive());
}
}
//运行结果:
begin=false
end=true
run=true
*说明:*虽然在上面示例中打印的值为true,但此值是不确定的。打印true值是因为myThread线程还未执行完毕,所以输出true。如果更改代码如下:
/*
* 测试类
*/
public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
System.out.println("begin=" + myThread.isAlive());
myThread.start();
Thread.sleep(1000);
System.out.println("end=" + myThread.isAlive());
}
}
//运行结果:
begin=false
run=true
end=false
上述代码运行的结果输出为false,因为myThread对象已经在1秒之内执行完毕。
##sleep()方法
**功能:**在指定的毫秒数内让当前“正在执行的线程”休眠(暂停执行)。这个“正在执行的线程”是指this.currentThread()返回的线程。
##getId()方法
**功能:**取得线程的唯一标识。
public class Test {
public static void main(String[] args) throws InterruptedException {
Thread runThread = Thread.currentThread();
System.out.println(runThread.getName() + " " + runThread.getId());
}
}
//运行结果为:
main 1
##停止线程
3种终止正在运行的线程的方法
- 使用退出标志,使线程正常退出。即,当run方法完成后线程终止。
- 使用stop方法强行终止线程。不推荐使用,stop和suspend及resume方法都已作废过期。
- 使用interrupt方法中断线程。调用interrupt()方法仅仅是在当前线程中打了一个停止的标记,并不是真的停止线程。
判断线程的状态是否停止?
- this.interrupted():测试当前线程是否已经是中断状态,执行后具有将状态标志清除为false的功能。当前线程是指运行this.interrupted()方法的线程。
- this.isInterrupted():测试线程Thread对象是否已经是中断状态,但不清除状态标志。
##暂停线程
暂停线程意味着此线程还可以恢复运行。
使用suspend()方法暂停线程,使用resume()方法恢复线程的执行。
suspend与resume方法的缺点:独占、不同步。
##yield方法
**功能:**放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间。
**缺点:**放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。
##线程的优先级
在操作系统中,线程可以划分优先级,优先级高的线程得到的CPU资源较多,也就是CPU优先执行优先级较高的对象中的任务。
设置线程的优先级使用setPriority()方法。此方法在JDK的源码如下:
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
}
在Java中,线程的优先级分为1~10这10个等级,如果小于1,或大于10,则JDK抛出异常throw new IllegalArgumentException()。
JDK中使用3个常量来预置定义优先级的值。代码如下:
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是一样的。
-
**线程优先级具有规则性:**优先级高的线程总是大部分先执行完,但并不是高优先级的线程全部先执行完。当线程优先级的等级差距很大时,谁先执行完和代码的调用顺序无关。
-
**线程优先级具有随机性:**优先级较高的线程不一定每次都先执行完。
-
线程优先级高的运行得快
##守护线程
在Java线程中有两种线程:用户线程和守护线程。
守护线程是一种特殊的线程,它的“特性”有陪伴的含义,当进程中不存在非守护线程了,则守护线程自动销毁。典型的守护线程就是垃圾回收线程。
最后
以上就是无聊眼神为你收集整理的Java多线程核心类Thread(《Java多线程编程核心技术》学习笔记(一))第一章:Java多线程技能的全部内容,希望文章能够帮你解决Java多线程核心类Thread(《Java多线程编程核心技术》学习笔记(一))第一章:Java多线程技能所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复