Thread 类的基本用法


前言

在现代编程中,多线程编程已经成为了一种必备的技能。无论是在后端服务器编程,还是在移动设备和桌面应用程序开发中,都需要使用多线程来提高应用程序的性能和响应速度。Java中提供了丰富的多线程编程支持,其中最核心的就是Thread类。通过Thread类,可以轻松地创建线程,并且可以控制线程的运行状态。在本篇博客中,我将介绍Thread类的基本用法,包括线程创建、中断、等待、休眠和获取线程实例等方面,希望可以为读者提供一些帮助。

一.线程的创建

多线程已经成为了一种普遍存在的并发编程方式。而线程的创建是多线程编程的基础,也是最重要的一部分。在Java中,线程的创建通常是通过继承Thread类或者实现Runnable接口来完成的。对于每个线程,都需要指定一个任务或者一组任务,线程会按照一定的顺序来执行这些任务。在本篇博客中,我将介绍如何使用Java语言来创建线程,包括如何继承Thread类或者实现Runnable接口,以及如何指定任务和启动线程等方面,希望可以为读者提供一些参考。


1.1 继承Thread的方式去创建线程

代码如下:

class MyThread extends Thread{
    @Override
    public void run(){
        while (true){
            System.out.println("hello t");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}
public class ThreadDemo1 {
    public static void main(String[] args) {
        Thread t=new MyThread();
        //start会创建 一个新线程
        t.start();
        while (true){
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


1.2 通过实现Runnable接口创建线程

//实现接口的方式去定义线程
class  MyRunnable implements Runnable{

    @Override
    public void run() {
        while (true){
            System.out.println("hello t");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class ThreadDemo2 {
    public static void main(String[] args) {
        MyRunnable runnable =new MyRunnable();
        Thread t=new Thread(runnable);
        t.start();
        while (true){
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

}


1.3 使用匿名内部类创建线程

这里将介绍俩种实现方式
以下是第一种方式,就是继承thead的方式去实现

//使用匿名内部类实现继承thread
public class ThreadDemo3 {
    public static void main(String[] args) {
        Thread t=new Thread(){
            @Override
            public void run(){
            while (true){
                System.out.println("hello t");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            }
        };
        t.start();
        while (true){
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

还有另外一种实现runable接口的方式去实现线程的创建

//匿名内部类实现ThreadRunable接口

public class ThreadDemo4 {
    public static void main(String[] args) {
        Thread t=new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello t");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        while (true){
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


1.4 使用lambda 表达式创建 Runnable 子类对象

public class ThreadDemo5 {
    public static void main(String[] args) {
        Thread t=new Thread(() ->{
            while (true){
                System.out.println("hello t");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        while (true) {
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

当你创建一个线程后,上面任意一种创建方式都是可以的,而且我们个人推荐的话,肯定是最后一种,使用lambad表达式,这样只能说,看起来十分的有高级感(仅代表个人观点).
运行的结果如下:
在这里插入图片描述

这俩个线程会交替执行,接下来,再来介绍一下,里面有一个start方法和run方法的区别:
run() 方法只是线程的一个普通方法,调用它不会创建一个新的线程,而只是按顺序执行其中的代码。因此,如果直接调用 run() 方法,那么其中的代码会在当前线程中执行,不会开启新的线程。

start() 方法才是真正启动一个新线程并开始执行其中的 run() 方法。当调用 start() 方法时,Java 会创建一个新的线程,并在新的线程中执行 run() 方法中的代码。因此,如果要启动一个新线程并执行其中的代码,就必须使用 start() 方法。

知道了上述的一个叙述之后,我们大概就知道,当主线程main调用t.start()方法的时候,另外一个线程就已经启动,开始执行run方法.代表另一个线程线程已经开始,但同时主线程也在启动.进而产生并发.


二.线程中断

我们现来具体的描述一下 ,什么是线程中断,我们来描述一下:线程中断是指在多线程程序中,中断正在运行的线程的执行,通常是由其他线程通过调用目标线程的interrupt()方法来实现。被中断的线程可以捕获这个中断信号并做出相应的处理,例如终止线程的执行或者进行一些清理工作。

说了这么一大堆,简单就是让程序停下来.
我们来假设一个情况,大家看下面这个代码,我们看下面一个代码

public class ThreadDemo9 {
    //线程的中断
    /*
    线程的中断意思就是停止的意思
     */

    public static void main(String[] args) {

        Thread t =new Thread(() -> {
            while (true) {
                System.out.println("hello t");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

这个代码的执行过程肯定就是死循环,我们要考虑怎么终止这个线程.
具体的思路如下:
1.在while循环中打一个标签
2.最后主线程执行结束时,更改标签.

public class ThreadDemo9 {
    //线程的中断
    /*
    线程的中断意思就是停止的意思
     */
    public static boolean isQuit=false;
    public static void main(String[] args) {
        
        Thread t =new Thread(() -> {
            while (!isQuit) {
                System.out.println("hello t");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("线程终止");
        });
        t.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        isQuit =true;

    }
}

这样看,我们是不是可以起到一个中断线程的一个流程了?不过java早就给我们,准备好了一套它的中断程序的方法.
具体的说明如下:

public class ThreadDemo10 {
    public static void main(String[] args) {
        Thread t=new Thread(() ->{
            //currentThread 获取当前的线程实例
            //此处currentThread 得到的对象就是t
            //isInterrupted 就是t对象的自带的一个标志位
            while (!Thread.currentThread().isInterrupted()){
                System.out.println("hello t");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
            //停止策略
        }
        //把 t 内部的标志位设置成true
        t.interrupt();
    }
}

当然,如果你看到这里,你觉的中断程序就结束了,那你就错了,这里运行程序的结果入下:
在这里插入图片描述
这里的话,我们按照上面的思路去改写代码,发现并程序并没有停止,而是继续往下执行,并且还抛出了一个错误,具体怎么回事,让我们一起探讨一下这其中的原因,这时候就要解释一下interrupt方法的作用,当然具体的作用,如下所示:
第一种情况
1.设置标志位为true
2.如果该线程正在阻塞中(比如在执行sleep)
此时就会把阻塞状态唤醒.
通过抛出异常的方式让sleep 立即结束.
第二种情况
当sleep被唤醒的时候, sleep 会自动的把 islnterrupted标志位给清空(true -> false)


具体的总结,如下:
调用interrupt()方法并不会立即中断线程的执行,而是会向目标线程发送一个中断信号,目标线程会在执行过程中检查自己是否被中断,如果被中断,则会抛出InterruptedException异常,通常需要在catch块中进行异常处理,比如进行资源释放等操作,最终退出线程。
需要注意的是,interrupt()方法并不会立即停止线程的执行,如果线程在等待I/O或者获取锁等阻塞状态下被中断,则会抛出InterruptedException异常,但是线程仍然持有锁或者继续等待I/O操作。此时需要线程自己检查中断状态并做出相应的处理,例如释放锁或者停止I/O操作等。
总之,interrupt()方法用于向目标线程发送中断信号,具体的中断处理需要目标线程自己根据自己的逻辑来决定,中断并不是一种强制性的控制机制,需要在代码中显式处理中断信号.


解释完这个方法以后,我们就来想一下怎么才能中断t线程呢?了解了上面的规律以后,我画个示意图,大家再理解一下
在这里插入图片描述

解决方法:就是在抛出异常的时候,我们结束循环就行了

public class ThreadDemo10 {
    public static void main(String[] args) {
        Thread t=new Thread(() ->{
            //currentThread 获取当前的线程实例
            //此处currentThread 得到的对象就是t
            //isInterrupted 就是t对象的自带的一个标志位
            while (!Thread.currentThread().isInterrupted()){
                System.out.println("hello t");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;
                }
            }
        });
        t.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
            //停止策略
        }
        //把 t 内部的标志位设置成true
        t.interrupt();
    }
}


三.线程等待

这个东西也很好理解,大家想象一个场景,你排队取钱的时候,你是不是要等待前一个人取完以后,你才可以存钱或者取钱,简单而言这就是线程等待.

就比如下面这串代码,你觉得谁想执行?

public class ThreadDemo11 {
    //线程等待的例子
    public static void main(String[] args) throws InterruptedException {
        Thread t =new Thread(() ->{
            System.out.println("hello t");
        });
        t.start();
        System.out.println("hello main");
    }
}

其实可能是hello main 先执行,也有可能是hello t 先执行,都不一定,但我们有时候,可以决定谁先执行,java的Thread提供了一个 jion方法,下面是这个方法的说明:

Thread类的join()方法用于等待当前线程结束后再执行后续代码,也就是将当前线程加入到目标线程的执行流程中,等待目标线程执行完毕后再执行当前线程。
调用join()方法会使当前线程阻塞,直到目标线程执行完毕或者等待超时才会继续执行。如果目标线程已经执行完毕,则join()方法会立即返回;如果目标线程未执行完毕,则当前线程会一直等待,直到目标线程执行完毕才会继续执行。
简单来说,谁调用谁阻塞

接下来展示一下代码:

public class ThreadDemo11 {
    //线程等待的例子
    public static void main(String[] args) throws InterruptedException {
        Thread t =new Thread(() ->{
            System.out.println("hello t");
        });
        t.start();
        t.join();
        System.out.println("hello main");
    }
}

在这里插入图片描述

四 .线程休眠

线程休眠是通过 Thread 类中的 sleep() 方法实现的。当一个线程调用 sleep() 方法时,它会进入休眠状态,暂停执行一段时间,然后重新开始执行。
其实上面有很多次让线程休眠代码展示,我这里就不做过多叙述了.

public class MyThread implements Runnable {
    public void run() {
        try {
            // 执行任务
            Thread.sleep(1000); // 休眠 1 秒
        } catch (InterruptedException e) {
            // 处理异常
        }
   

五 .获取线程实例

基本上是获取当前线程,这里应该经过上面的叙述之后,大家应该已经相当熟悉了.
代码如下:

public class ThreadDemo {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName());
   }
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忘忧记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值