目录
目录
2.public static boolean interrupted()
3.public boolean isInterrupted()
一.Java的线程模型
所谓线程模型就是虚拟CPU、执行代码和操作数据三者的封装体。在java中,线程模型通过java.lang包中的Thread类描述和声明。当然,除了Thread类可以支持线程外,还有Runnable接口,Object类,ThreadGroup类,ThreadDeath类。
这五者的关系如👇图:
二.创建线程的五种方法
1.继承Thread类
覆盖run()方法。
class myThread extends Thread{
@Override
public void run() {
System.out.println("继承Thread创建线程");
}
}
2.实现Runnable接口
1.将一个类实现Runnable接口
class myThread implements Runnable{
@Override
public void run() {
System.out.println("继承Runnable创建线程");
}
}
2.创建线程对象
使用Thread类的构造方法,即 Thread 对象名 = new Thread(实现Runnable接口类的对象);
后对象名.start()启动线程。
3.匿名内部类创建Thread子类
public static void main(String[] args) {
Thread t = new Thread(){
public void run(){
System.out.println("匿名内部类创建Thread子类,重写run方法");
}
};
t.start();
}
4.匿名内部类创建Runnable子类
public static void main(String[] args) {
Thread t = new Thread(new Runnable()
{
public void run(){
System.out.println("匿名内部类创建Runnable子类,重写run方法");
}
});
t.start();
}
5.Lambad创建Runnable子类
public static void main(String[] args) {
Thread t = new Thread(()-> System.out.println("Lambda表达式创建Runnable子类"));
t.start();
}
三.线程中断
中断线程不是让线程直接停下来,而是通知线程结束,而线程具体的执行,取决于线程自身的代码。Thread类关于中断有三个实例方法,interrupt(),interrupted(),isinterrupted()。
1.public void interrupt()
当调用这个方法时,调用这个方法的线程对象会通知目标线程中断,并将目标线程的中断标志位设置为true。如果线程处于wait(),join(),sleep()阻塞状态,则会抛出异常。
2.public static boolean interrupted()
用于判断目标线程是否设置中断标志位,调用后会清除标志位。
使用interrupted()来中断一个线程:
public static void main(String[] args) {
Thread t = new Thread(){
public void run(){
while (true){
if(Thread.interrupted()){
System.out.println(Thread.currentThread().getName()+" "+"has interrupting");
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
System.out.println("hello");
}
}
};
t.start();
try {
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.interrupt();
}
3.public boolean isInterrupted()
用于判断目标线程是否设置中断标志位,调用后不会清除标志位。
使用isInterrupted()来中断一个线程:
public static void main(String[] args) {
Thread t = new Thread(){
public void run(){
while (!Thread.currentThread().isInterrupted()){
System.out.println("hello");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
};
t.start();
try {
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.interrupt();
}
两种运行结果相同:10秒内,每隔1秒打印1个hello,然后抛出异常后,结束线程。
以上这两种中断方法的可行性,都取决于sleep处理异常的代码,由于break的存在,线程才能顺利中断,所以catch代码的写法,决定了中断的结果,可以选择不中断,也可以选择过会中断,也可以立即中断,这一切都取决于编写代码的程序员本身。
四、等待线程
Thread类给了我们join()方法来让其他线程阻塞等待目标线程结束再运行。
当然Thread还给了我们join(long millis),join(long millis,int nanos)两个方法限定等待的最长时间,
而我们的join()方法是死等,如果在调用join之前,目标线程已经结束了,就不会阻塞等待。
等待线程实现代码:
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(){
public void run(){
int i = 0;
while(i<3){
System.out.println("t running");
try {
sleep(1000);
i++;
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("t end");
}
};
System.out.println("main start");
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread.sleep(2000);
System.out.println("main end");
System.out.println("over");
}
如果是没有加join()的运行结果:
main start
t running
t running
main end
over
t running
t end
很明显main线程并没有等待t线程,而是二者一块运行。
运行结果:
main start
t running
t running
t running
t end
main end
over
可见,main线程是等待了t线程执行完后,再继续执行。
以上就是本文的全部内容了。