[Java EE初阶]Thread 类的基本用法

本就无大事,庸人觅闲愁.



1. 线程创建

创建线程有五个方法
详情见我的另一个文章
https://editor.csdn.net/md/?articleId=128293107
分别是继承Thread,实现Runnable接口,使用匿名内部类继承Thread,使用匿名内部类,实现Runnale接口,使用Lambda表达式.

2. 线程中断

线程中断是t通过标志位通知线程快要终止了,线程接收到信号后,可以加入自己的操作,做出不同反应.

2.1 通知终止后立即终止

如下代码

public class InterruptedThread {
    public static void main(String[] args)throws InterruptedException {
        Thread t = new Thread(()->{
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("hello thread");
                break;
            }
        });
        t.start();
        t.sleep(1000);
        t.interrupt();
    }
}

说明:
1.Thread.currentThread()的作用是获取当前的进程
2.isInterrupted()源码如下
在这里插入图片描述
线程调用这个函数,获取标志位,也就是true或者false
返回值是false时,通知这个线程未被终止,while()循环继续.
返回值是true时,通知线程即将被终止.是否选择终止,取决于线程之后的操作.
3.t.interrupt(),将标志位改为true,在上述代码中,线程标志位为true时,while循环结束,无其他操作,线程立刻终止.

执行结果
在这里插入图片描述

2.2 通知终止,通知之后线程继续执行

	public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        t.sleep(1000);
        t.interrupt();
    }
   

结果如下图
在这里插入图片描述

说明:
调用t.interrupt();将标志位改为true,如果线程正在sleep,interrupt()会触发sleep内部的异常,导致sleep提前返回,将标志位重新改为false,唤醒进程.
所以,在提醒终止后,线程未选择终止,而是继续执行

2.3 通知终止后,添加操作后终止

	 public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    try {
                        System.out.println("我是添加的操作");
                        System.out.println("1 + 1 = 2");
                        Thread.sleep(500);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                    break;
                }
            }
        });
        t.start();
        t.sleep(1000);
        t.interrupt();
    }

结果如下图
在这里插入图片描述
说明:
t.interrupt(),将标志位改为true,但线程正在sleep,触发catch异常,之后try-catch捕获异常,可以在try中添加操作,之后break,直接跳出循环.

3. 线程等待

线程抢占式执行,随机调度,线程执行的顺序由操作系统操控,不可预知.
线程等待,目的是控制两个线程结束的顺序.
若是在t2中调用t1.join(),意味着t2会等待t1结束后才会终止自身进程.

	public static void main(String[] args) {
        System.out.println("main开始喽");
        Thread t = new Thread(()->{
            for(int i = 0; i < 3; i++){
                System.out.println("hello thread");
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t.start();
        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("main结束喽");
    }

在这里插入图片描述
t.join();执行此代码时,main()函数会等待t线程结束后,再结束自身调度.

4. 线程休眠

操作系统每次只会在就绪序列中选择合适线程执行.
调用sleep()函数,使线程从就绪序列置到阻塞序列
由于线程调度有时间开销,线程休眠结束后,线程唤醒之后不会立即被执行.

5. 获取线程实例

1.使用线程调度两个线程

	public static void concurrency() {
        // 使用两个线程分别完成自增.
        Thread t1 = new Thread(() -> {
            long a = 0;
            for(long i = 0; i < 100_0000_0000L; i++) {
                a++;
            }
        });
        Thread t2 = new Thread(() -> {
            long b = 0;
            for(long i = 0; i < 100_0000_0000L; i++) {
                b++;
            }
        });
        // 开始计时
        long beg = System.currentTimeMillis();
        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 结束计时
        long end = System.currentTimeMillis();
        System.out.println("并发执行时间: " + (end - beg) + " ms");
    }

2.正常调度两个线程

public static void serial() {
        // 为了衡量带没带的执行速度, 加上个计时的操作
        // currentTimeMillis 获取到当前系统的 ms 级时间戳.
        long beg = System.currentTimeMillis();

        long a = 0;
        for (long i = 0; i < 100_0000_0000L; i++) {
            a++;
        }
        long b = 0;
        for (long i = 0; i < 100_0000_0000L; i++) {
            b++;
        }

        long end = System.currentTimeMillis();
        System.out.println("执行时间: " + (end - beg) + " ms");
    }

时间对比,会发现使用线程之后,大大减小时间开销.
在这里插入图片描述


  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值