Thread类的基本用法

✨个人主页: 不漫游-CSDN博客

前言

前面已经总结过线程与进程的区别-->http://t.csdnimg.cn/UIURX

这次咱们来总结下线程的一些常见用法。

线程创建

继承 Thread, 重写 run

class Main extends Thread{
    public void run(){
        while(true){
        System.out.println("hello,Thread");
            try {
                Thread.sleep(1000);//休眠一秒再打印
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
}}
public class Demo1 {
    public static void main(String[] args) {
        Main main=new Main();
        main.start();//创建了一个线程
        while(true){
        System.out.println("hello,Demo1");
            try {
                Thread.sleep(5000);//休眠5秒再打印
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    }

结果如图,观察这段代码,我们重写了Thread类自带的方法run, 用于无限打印语句。同时除了主线程main函数,还创建了一个main线程(只是名字相同)。

但是,通过设置打印间隔,更好地观察结果-->Demo1和第一次的Thread几乎是同时出现,后续只是设置的打印间隔不同。

实现 Runnable, 重写 run

class MyThread implements Runnable{
    public void run(){
        while(true){
        System.out.println("MyThread!");
            try {
                Thread.sleep(2000);//每隔两秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
}
}

public class Demo2 {
    public static void main(String[] args) throws InterruptedException {
        Runnable runnable=new MyThread();
        Thread t=new Thread(runnable);
        t.start();//创建了一个t线程

        //main函数原来要执行的
        while (true){
        System.out.println("Demo2");
        Thread.sleep(5000);//每隔5秒
    }
}
}

这里就是重写了Runnable接口里面的方法,和第一种的继承大同小异,只不过间隔不同。

结果如图~ 

 


继承 Thread, 重写 run, 使用匿名内部类

public class demo3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(){
         //重写run()
          public void run(){
              while(true){
              System.out.println("hello world");
                  try {
                      Thread.sleep(5000);//每隔5秒
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
          }
        };
        t.start();创建一个t线程

        while(true){
            System.out.println("1122");
            Thread.sleep(1000);//每隔一秒
        }
    }
}

分别来看两个不同的线程的执行情况: 

线程 ​t​:

首先这是一个匿名内部类,继承自 ​Thread​类。
然后重写​run​方法,每隔5秒钟打印一次"hello world"。
在每次打印后,线程会调用 ​Thread.sleep(5000)​方法休眠5秒钟。

主线程:

在 ​main​方法中,每隔1秒钟打印一次"1122"。
在每次打印后,主线程会调用 ​Thread.sleep(1000)​方法休眠1秒钟。

结果如图~ 

 


实现 Runnable, 重写 run, 使用匿名内部类

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

这里就和上一个是基本一致的,只不过在Thread实例化的时候加入了 new Runnable().实现接口里面的方法。 


使用 lambda 表达式

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

这里就要注意格式了,没有出现run方法的声明,但是用->代替了,基本格式就是这样~

Thread t=new Thread(()->{
...
//具体操作
});

 

Thread类中run和start的区别

通过上述线程创建的不同方法,简单总结下两者的区别:

​​run()​ 方法:该方法包含了线程运行时所执行的代码,也称为“线程的入口”。

可以通过直接调用 ​run()​ 方法来执行线程,但这并不会创建新的线程,而是在当前线程中执行 ​run()​ 方法的代码。就和以前一样的方法调用。
​​start()​ 方法:该方法会创建一个新的线程,并在新的线程中调用 ​run()​ 方法。这就是创建和启动线程的正确方式。


线程中断

在Java中,线程中断是一种协作机制,用于向线程发送一个信号,表明它应该停止正在执行的任务。线程可以通过检查中断状态来决定是否响应这个信号。

但中断本身并不会强制线程停止执行,而是由线程自己决定如何处理中断。

public class InterruptExample {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            //无限循环,直到线程被中断
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("Thread is running.");
                try {
                    //线程休眠1秒钟
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    //当线程在休眠时被中断,会抛出InterruptedException异常
                    System.out.println("Thread interrupted while sleeping.");
                    //恢复线程的中断状态,以便循环中的isInterrupted()检查可以正确检测到中断状态
                    Thread.currentThread().interrupt();
                }
            }
            //线程检测到中断状态,打印停止消息并退出循环
            System.out.println("Thread is stopping.");
        });

        //启动线程 t
        t.start();

       Thread.sleep(5000);

        //中断线程 t
        t.interrupt();
    }
}

1. 创建了一个新的线程 `t`,它在一个无限循环中运行,每隔1秒钟打印一次"Thread is running."。
2. 在主线程中,休眠5秒钟后便调用 t.interrupt() 方法来中断线程 t。
3. 当线程 t 在 `sleep` 方法中被中断时,会抛出 InterruptedException 异常,并在捕获到这个异常后打印一条消息。
4. 在捕获到 InterruptedException异常后,通过调用 Thread.currentThread().interrupt()方法来恢复线程的中断状态,这样循环中的 isInterrupted()检查可以正确地检测到中断状态。
5. 当 isInterrupted() 返回 true时,线程会打印Thread is stopping.并退出循环。

结果如图~ 


线程等待

对于线程的执行顺序,其特点-->抢占式执行 决定了无法确定执行顺序。

但结束顺序就不一定了,线程等待中的 join() 方法就是为此服务~

public class demo11 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                System.out.println("t线程");
            }
            try {
                Thread.sleep(1000); //让线程 t 休眠 1 秒钟
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("t线程执行结束");
        });

        System.out.println("主线程开始等待t线程");
        t.start();
        t.join(); //主线程调用 t.join(),等待线程 t 完成执行
        System.out.println("主线程结束等待");
    }
}

调用join()时就记住-->  在a线程中调用b.join(),意思即是a等待b执行结束,a才继续执行!  

在这里,a线程就是主线程,b.join()即是t.join(),即只有t线程执行结束后,主线程才会继续执行~ 

结果如图~

当然,这是无参版本的,那就是“死等”。只有等到b线程执行结束才可以。加上参数就可以规定等待时间了。


线程休眠

在上面已经见过很多次了,就是线程中的sleep ()方法,以便让出 CPU 资源给其他线程使用。

public class demo12 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (true) {
                System.out.println("hello");
                try {
                    Thread.sleep(5000); //让线程休眠 5 秒钟
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
    }
}

每隔5秒打印一次。结果如图~


获取线程实例

获取线程实例通常指的是获取当前正在执行的线程对象。

咱们可以使用 Thread.currentThread()方法来获取当前线程的实例。这个方法返回一个Thread对象,表示当前正在执行的线程。

public class demo13 {
    public static void main(String[] args) {
        //获取主线程实例
        Thread mainThread = Thread.currentThread();
        System.out.println("主线程名称: " + mainThread.getName());

        //创建并启动一个新的线程
        Thread newThread = new Thread(() -> {
            //获取新线程实例
            Thread currentThread = Thread.currentThread();
            currentThread.setName("新线程");
            System.out.println("新线程名称: " + currentThread.getName());
        });
        newThread.start();
    }
    }

结果如图~

看到最后,如果觉得文章写得还不错,希望可以给我点个小小的赞,您的支持是我更新的最大动力

相关推荐

  1. Thread 基本

    2024-07-19 16:56:04       23 阅读
  2. 总结 Thread 基本

    2024-07-19 16:56:04       24 阅读
  3. Thread基本

    2024-07-19 16:56:04       20 阅读
  4. Python 中 Thread 线程

    2024-07-19 16:56:04       53 阅读
  5. pymysql基本

    2024-07-19 16:56:04       55 阅读
  6. @ConfigurationProperties 基本

    2024-07-19 16:56:04       37 阅读
  7. mysql基本

    2024-07-19 16:56:04       30 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-19 16:56:04       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-19 16:56:04       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-19 16:56:04       58 阅读
  4. Python语言-面向对象

    2024-07-19 16:56:04       69 阅读

热门阅读

  1. css2024

    2024-07-19 16:56:04       21 阅读
  2. Jangow

    Jangow

    2024-07-19 16:56:04      22 阅读
  3. new一个对象的具体步骤

    2024-07-19 16:56:04       21 阅读
  4. Hive 的 classpath 简介

    2024-07-19 16:56:04       19 阅读
  5. ArcGIS Pro SDK (九)几何 7 多点

    2024-07-19 16:56:04       21 阅读
  6. 网络安全相关竞赛比赛

    2024-07-19 16:56:04       25 阅读
  7. Open3D点云配准介绍-点云之间进行配准

    2024-07-19 16:56:04       21 阅读
  8. windows关闭双击过后的jar 包

    2024-07-19 16:56:04       20 阅读
  9. windows下flutter国内镜像恢复成外网链接

    2024-07-19 16:56:04       17 阅读