Thread类的基本用法

本文详细介绍了Java中线程的创建方式(继承Thread类、实现Runnable接口、匿名内部类和lambda表达式)、线程中断的处理(自定义标记位和interrupt()方法)、线程等待join()和休眠sleep()方法,以及如何获取线程实例。
摘要由CSDN通过智能技术生成

⭐ 作者:小胡_不糊涂
🌱 作者主页:小胡_不糊涂的个人主页
📀 收录专栏:JavaEE
💖 持续更文,关注博主少走弯路,谢谢大家支持 💖


在这里插入图片描述

1. 线程创建

1.1 继承Thread类

class MyThread extends Thread{
    public void run(){
        System.out.println("继承Thread,重写run");
    }
}
public class TestDemo1{
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();//启动线程
    }
}

1.2 实现Runnable接口

class MyRunnable implements Runnable{
    public void run(){
        System.out.println("实现Runnable接口");
    }
}
public class TestDemo1{
    public static void main(String[] args) {
        Thread thread=new Thread(new MyRunnable());
        thread.start();
    }
}

1.3 使用匿名内部类创建Thread子类对象

public class TestDemo1{
    public static void main(String[] args) {
        Thread thread=new Thread(){
            public void run(){
                System.out.println("这是一个线程");
            }
        };
        thread.start();
    }
}

1.4 使用匿名类创建 Runnable 子类对象

public class TestDemo1{
    public static void main(String[] args) {
        Thread thread=new Thread(new Runnable(){
            public void run() {
                System.out.println("实现Runnable,重写run,使用匿名内部类");
            }
        });
        thread.start();//启动线程
    }
}

1.5 使用lambda 表达式

public class TestDemo1{
    public static void main(String[] args) {
        Thread thread=new Thread(()->{
                System.out.println("使用lambda表达式");
        });
        thread.start();
    }
}

2. 线程中断

当我们想要让一个正在执行的线程停止时,该怎么做呢?

2.1 使用自定义的变量来作为标记位

ublic class TestDemo2 {
    private static volatile boolean isquit=false;
    public static void main(String[] args) {
        Thread thread=new Thread(()->{
            while(!isquit){
                System.out.print(Thread.currentThread().getName());
                System.out.println("线程工作中...");
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            //线程运行完毕
            System.out.println("线程工作完毕");
        });
        thread.start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        isquit = true;
        System.out.println("让 thread 线程结束!");
    }
}

需要给标志位上加 volatile 关键字才能进行修改

2.2 调用interrupt()方法来通知

方法说明
public void interrupt()中断对象关联的线程
public static boolean interrupted()判断当前线程的中断标志位是否设置
public bool isInterrupted()判断对象关联的线程标志位是否设置
public class TestDemo2 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread=new Thread(()-> {
            //while(!Thread.interrupted()){
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("线程工作中...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    break;
                }
            }
        });
        thread.start();
        Thread.sleep(2000);
        // 使用一个 interrupt 方法, 来修改刚才标志位的值
        System.out.println("让 thread 线程结束");
        thread.interrupt();
    }
}

thread 收到通知的⽅式有两种:

  1. 如果线程因为调⽤ wait/join/sleep 等⽅法⽽阻塞挂起,则以 InterruptedException 异常的形式通知,清除中断标志。
    当出现 InterruptedException 的时候,要不要结束线程取决于catch 中代码的写法。可以选择忽略这个异常,也可以跳出循环结束线程。
  2. 否则,只是内部的⼀个中断标志被设置,thread 可以通过。
    Thread.currentThread().isInterrupted()判断指定线程的中断标志被设置,不清除中断标志,这种方式通知收到的更及时,即使线程正在 sleep 也可以马上收到。

3. 线程等待-join()

有时,我们需要等待⼀个线程完成它的⼯作后,才能进⾏⾃⼰的下⼀步⼯作。

public class TestDemo3{
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            int n = 5;
            for (int i = 0; i < n; i++) {
                System.out.println("我是一个线程, 正在工作中...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("线程执行结束");
        });

        t.start();
        t.join();  // 线程等待
        System.out.println("这是主线程, 期望在 thread 结束后打印");
    }
}

在这里插入图片描述

如果将t.join()注释,结果会是什么呢?
在这里插入图片描述

方法说明
public void join()等待线程结束
public void join(long millis)等待线程结束,最多等待millis毫秒
public void join(long millis,int nanos)同上

4. 线程休眠-sleep()

为线程的调度是不可控的,所以,该⽅法只能保证实际休眠时间是⼤于等于参数设置的休眠时间的。

方法说明
public static void sleep(long millis) throws InterruptedException休眠当前线程run方法
public static void sleep(long millis,int nanos) throws InterruptedException可以更高精度的休眠线程
public class TestDemo4 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(()->{
            System.out.println("t1正在执行");
        });
        Thread t2=new Thread(()->{
            System.out.println("t2正在执行");
        });
        t1.start();
        t2.start();
    }
}

上面的执行过程中,我们无法控制t1与t2的先后执行顺序,运行时就会产生:
在这里插入图片描述

但是当我们让main线程在执行t1线程时,进入有限的休眠状态,就可以保证t2不会来干扰t1

public class TestDemo4 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(()->{
            System.out.println("t1正在执行");
        });
        Thread t2=new Thread(()->{
            System.out.println("t2正在执行");
        });
        t1.start();
        Thread.sleep(1000);
        t2.start();
    }
}

在这里插入图片描述

5. 获取线程实例

方法说明
public static Thread currentThread();返回当前线程对象的引用
public class TestDemo5 {
    public static void main(String[] args) {
        Thread thread=Thread.currentThread();
        System.out.println(thread.getId());//1
        System.out.println(thread.getName());//main
    }
}
public class TestDemo5 {
    public static void main(String[] args) {
       // Thread thread=Thread.currentThread();
        Thread thread=new Thread();
        System.out.println(thread.currentThread().getId());//1
        System.out.println(thread.getName());//Thread-0
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值