JavaEE——Thread类详解
1.1线程创建
线程如何创建?
通过Thread类实例化对象这并没有创建一个新线程,需要再通过Thread类自带的方法start()或者run()启动才算线程创建了。
Thread实例化对象的两种方法:
- 继承Thread类,重写run()方法
class myThread extends Thread { /创建了一个类myThread继承了Thread类
public void run() { /重写run方法
System.out.println("hello thread");
}
}
}
public class demo1 {
public static void main(String[] args) {
int a=0;
Thread t= new myThread(); /向上转型
t.start(); /创建线程
}
}
- 定义MyRunnable类,实现Runnable接口
public class MyRunnable implements Runnable {
@Override
public void run() {
//run方法线程体
for (int i = 0; i < 20; i++) {
System.out.println("我在吃饭----"+i);
}
}
public static void main(String[] args) {
//创建runnbale接口的实现类对象
MyRunnable t = new MyRunnable();
//创建线程对象,通过线程对象来开启我们的线程,代理
new Thread(t).start();
}
}
还有匿名内部类重写和lambda表达式的方式,其实原理差不多,在这不多赘述,不是本文重点。
1.2 线程中断
线程中断从字面就能理解,停止一个线程,那么如何停止呢?
有以下几种方法:
- 自定变量作为标志位
需要用volatile关键字自定一个变量
public class demo2 {
public static class MyRunnable implements Runnable {
public volatile boolean isQuit = false; /自定标志位
@Override
public void run() {
while(!isQuit) {/如果isQuit为true则跳出循环
System.out.println("正在执行");
}
System.out.println("进程中断");
}
}
public static void main(String[] args) throws InterruptedException {
MyRunnable target = new MyRunnable();
Thread t = new Thread(target);
t.start();
Thread.sleep(5000);
System.out.println("使进程中断");
target.isQuit=true;/修改为true停止while循环
}
}
在这里定义了isQuit变量,当isQuit为true时,while循环终止
- 使用 Thread.interrupted() 或者 Thread.currentThread().isInterrupted() 代替自定义标志位。
先大致看看用法:
class MyRunnable implements Runnable {
@Override
public void run() {
while(!Thread.interrupted()) {/这里就用Thread.interrupted()代替了标志位
System.out.println("正在执行");
}
System.out.println("执行中断");
}
}
public class demo3 {
public static void main(String[] args) throws InterruptedException {
MyRunnable tar = new MyRunnable();
Thread t = new Thread(tar);
t.start();
Thread.sleep(3000);
t.interrupt();/使用Thread自带方法中断线程
}
}
其实就是用Thread.interrupted() 或Thread.currentThread().isInterrupted() 代替了刚刚的isQuit()
程序运行结果:
Thread.interrupted() 和 Thread.currentThread().isInterrupted() 都可以代替标志位,但是他们略有不同。
- Thread.interrupted() 当它判断到中断标志被设置时,会清除中断标志
- Thread.currentThread().isInterrupted() 当它判断到中断标志被设置时,不会清除中断标志
1.3线程等待
Join()方法可以时线程等待另一个线程完成操作之后再继续运行,比如下列代码
class MyRunnable2 implements Runnable {
@Override
public void run() {
System.out.println("线程正在执行");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class demo5 {
public static void main(String[] args) throws InterruptedException {
MyRunnable2 tar = new MyRunnable2();
Thread t = new Thread(tar);
t.start();
t.join();
System.out.println("hello");
}
}
main线程会等待 t 线程执行结束后再执行后面的打印hello
1.4线程休眠
线程休眠我们会使用到sleep()方法
它会使线程暂停一段时间,之后判断是否有其他线程中断了当前线程,如果被中断了就抛出InterruptException异常,在这里本人之前有一个误区,就是认为当sleep休眠之后,线程就停止了,一旦休眠立马抛出异常,后面才发现休眠时不会抛异常,而是休眠后检测线程是否被中断,中断才抛出异常
此外,我们看看sleep源码里的注释
注意后面一句话:引发此异常时,将清除当前线程的中断状态
也就是说当sleep抛出异常后,它会将线程由中断状态恢复到运行状态。所以,它只是告诉你这里出现异常了,如何处理还是要看用户,你是要彻底中断它,还是怎么怎么样。
所以sleep()方法需要try catch
try {
sleep(1000);//休眠1s
} catch (InterruptedException e) {
e.printStackTrace();//打印异常信息
//看用户如何处理异常
}