线程的启动:
参考官方文档
调用线程的start方法,通知jvm虚拟机去调用该线程的run方法,结果是两个线程并发的执行,一个是当前线程(调用start方法的线程),一个执行run方法的线程
如示例:
public class ThreadTest {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println(Thread.currentThread().getName());
});
thread.start();
System.out.println(Thread.currentThread().getName());
}
}
打印出两个线程名称为:
main 执行start方法d main线程
Thread-0 新建的执行run方法的线程0
注意的点:
1.多个线程start方法的顺序并不能决定线程真正执行的顺序。
需要等待CPU的资源,是异步随机执行的,如下示例:
public class ThreadTest {
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ": run");
}
};
Thread thread1 = new Thread(r);
Thread thread2 = new Thread(r);
Thread thread3 = new Thread(r);
Thread thread4 = new Thread(r);
Thread thread5 = new Thread(r);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
}
}
打印结果是随机的:
Thread-0: run
Thread-2: run
Thread-1: run
Thread-3: run
Thread-4: run
2.start方法不能重复调用,哪怕线程已经执行完毕也不能再次执行,否则将抛出线程状态异常,后面说线程的状态可以了解。
3.和run方法的区别:为什么不用run方法启动线程
如文档解释,start方法是当前线程执行start方法,告诉jvm虚拟机用新建的线程是执行run方法。而run方法就是当前线程之间执行了run方法,并没有使用新建的线程。
停止线程:
使用interrupt()方法中断线程,需要注意的是,该方法是一个线程去通知另一个线程去中断,被中断的线程自身决定是否停止,非强行停止;
思考如下:
被停止线程更清楚该如何停止,比如某个线程a正在执行run方法,如果其它线程b调用了a的interrupt()方法通知其停止,a应该自身决定如何响应,是继续执行,还是纪录一些日志,处理完一个阶段的业务再停止,如果a被b强制停止,则a执行的业务将产生脏数据,安全性较差。所以停止线程的最佳方法就是通知该线程去停止,该线程可以自行判断自身是否已被中断(
isInterrupted()方法判断),然后合理响应;stop()方法,强制停止,已过时;
示例:
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
Runnable r = new Runnable() {
@Override
public void run() {
while (true) {
System.out.println("我一直在执行");
if (Thread.currentThread().isInterrupted()) {
System.out.println("好的,我停止了");
break;
}
}
}
};
Thread thread = new Thread(r);
thread.start();
Thread.sleep(10);
thread.interrupt();
}
}
打印结果:
...
我一直在执行
我一直在执行
我一直在执行
我一直在执行
我一直在执行
好的,我停止了
如代码示例,被通知中断的线程配合做了处理(if判断)自主决定中断还是继续执行;
进一步考虑,如果线程没有在执行,而是在阻塞状态,如下run示例:
public void run() {
while (true) {
System.out.println("我一直在执行");
Thread.sleep(10000);
if (Thread.currentThread().isInterrupted()) {
System.out.println("好的,我停止了");
break;
}
}
}
线程阻塞在sleep方法时,这时候外部线程通知中断,但这里已经阻塞无法进到if判断,该如何响应,sleep方法已经考虑到了,这个方法强制要求我们处理InterruptedException异常,即中断异常,来响应外部的中断通知。
如示例:
public void run() {
while (true) {
System.out.println("我一直在执行");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("好的我知道了");
}
if (Thread.currentThread().isInterrupted()) {
System.out.println("好的,我停止了");
break;
}
}
}
另外修改后的方法实际执行的话,while循环并没有停止,线程并没有结束,这是为什么呢?这是因为抛出异常的同时会将该线程的isInterrupted重置为false;可以查看InterruptedException的注释:
抛出InterruptedException的时候,会清除是否中断的标记位!
其它:
如果run方法执行完毕或抛出异常,该线程也会停止;
--- END ---
马上关注 / 码上杂谈