第1章 多线程技能
- 执行start()方法的顺序不代表线程启动的顺序。
- 实现Runnable()接口中,构造函数Thread(Runnable target)不光可以传入Runnable接口的对象,还可传入一个Thread类的对象,这样做完全可以将一个Thread对象中的run()方法交由其他的线程进行调用。
- 使用synchronized关键字对任意对象或方法进行加锁,加锁的这段代码称为“互斥区”或“临界区”。
- **run()和start()**的区别:前者是顺序执行,后者是并行的。
- currentThread():返回当前代码段正被哪个线程调用的信息。
- 构造函数是被main线程调用的。儿run方法是被名为Thread-0的线程调用的,run方法是自动调用的方法。
- this.getName():指的就是当前被调用线程的线程名称
Thread.currentThread.getName():指的是执行当前线程的线程名称
例子讲解
- isAlive():
- sleep():单位(ms)
- getIt():取得线程的唯一标识
- 停止线程:
- 停止线程的三种方法
- 使用退出标志
- 使用stop():暴力停止,已作废,不推荐
- 是用interrupt方法中断:只是在当前线程打了一个停止的标记,并不是真的停止线程
- 判断线程是否是停止状态
- this.interrupted():测试当前线程是否是中断状态,执行后具有将状态标志置为false的功能
- this.isInterrupted():测试线程Thread对象是否已经是中断状态,但不清除状态标志
- 使用异常法可以停止线程
Thread.java
package thread.stop.exception;
/**
* 通过抛异常法来停止线程
* @author: xianzhixianzhixian
* @date: 2018-12-10 21:05
*/
public class MyThread extends Thread {
@Override
public void run() {
super.run();
try {
for (int i=0;i<500000;i++){
if (this.isInterrupted()){
System.out.println("线程已停止,即将退出!");
throw new InterruptedException();
}
System.out.println("i="+(i+1));
}
} catch (InterruptedException e) {
//在此处添加throw即可跳出正在运行的线程
System.out.println("进入MyThread.java中的异常捕获块了!");
e.printStackTrace();
}
}
}
Run.java
package thread.stop.exception;
/**
* @author: xianzhixianzhixian
* @date: 2018-12-10 21:10
*/
public class Run {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
System.out.println("end!");
}
}
- 在沉睡中停止:
- 先sleep再使用interrupt()停止:抛出异常,并且清除停止状态值,使之变成false
- 先使用interrupt()停止,再sleep:抛出异常
- stop():
- 调用stop()会抛出java.lang.ThreadDeath异常,此异常通常不需要显示的捕捉。
- stop()会强制让线程停止,使一些请理性的工作得不到完成。另一种情况就是对锁定的对象进行了解锁,导致数据得不到同步的处理,出现数据不一致的情况。
- 使用return停止线程
- 当isInterrupted()==true时,执行return;
不建议使用,可能会存在多个return造成污染。推荐使用抛异常的方法,因为catch块中可以对异常的信息进行相关的处理,而且使用异常流能更好、更方便地控制程序的运行流程。
- 暂停/恢复线程
- suspend():暂停线程
resume():恢复线程 - 缺点
- 独占:易造成公共的同步对象的独占,使得其他线程无法访问公共同步对象
- 不同步:导致数据的不同步
- yield():放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。
- 线程的优先级
- 设置线程的优先级:setPriority()
- 线程的优先级具有继承性,比如A线程启动B线程,则B线程的优先级与A一样。
- 高优先级的线程总是大部分先执行完,但不代表高优先级的线程全部先执行完。
- 守护线程
- 当最后一个非守护线程结束时,守护线程也会结束,例如GC垃圾回收器。
- 通过**thread.setDaemon(true)**来设置线程为“守护线程”;将一个用户线程设置为守护线程的方式是在 线程对象创建 之前 用线程对象的setDaemon方法。