Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >话说 线程创建&启动&停止

话说 线程创建&启动&停止

原创
作者头像
木子的昼夜
修改于 2021-04-06 03:11:41
修改于 2021-04-06 03:11:41
1.2K0
举报

线程创建&启动&停止

线程啊是个好东西,但是平时工作很少自己创建线程,所以一些基础的操作可能就不容易记起来,这篇文章常看看有益身心健康

1. 创建
代码语言:txt
AI代码解释
复制
public class TestDeamon {
    public static void main(String[] args) {
        // lambda 表达式
        Thread t1 = new Thread(()->System.out.println("这是一个线程01!"));
        Thread t2 = new Thread(()->{
            System.out.println("这是一个线程02!");
        });
        // 匿名内部类
        Thread t3 = new Thread(){
            @Override
            public void run() {
                System.out.println("这是一个线程03!");
            }
        };
        // 继承Thread
        Thread t4 =new MyThread04();

        // 实现Runnable 参数是Runnable
        Thread t5 = new Thread(new MyRunnable());

        // 时效内
        // 启动线程
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }
}

/**
 * 继承Thread
 * public class Thread implements Runnable
 * thread是实现了Runnable接口
 */
class MyThread04 extends  Thread{
    @Override
    public void run() {
        System.out.println("这是一个线程04!");
    }
}

/**
 * 实现Runnable
 */
class MyRunnable implements   Runnable{
    @Override
    public void run() {
        System.out.println("这是一个线程05!");
    }
}
2. 启动
代码语言:txt
AI代码解释
复制
// 启动线程
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
输出:
这是一个线程01!
这是一个线程02!
这是一个线程03!
这是一个线程04!
这是一个线程05!

线程启动之后就会执行run方法

3. 停止线程/中断
3.1. 线程执行完 自己结束

执行完for循环 自动结束

代码语言:txt
AI代码解释
复制
// lambda 表达式
        Thread t1 = new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try{
                    Thread.sleep(1000);
                    System.out.println("===");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
3.2. stop 被废弃了

stop已经被废弃,stop太粗暴,不温柔,所以没人喜欢..

代码语言:txt
AI代码解释
复制
 // lambda 表达式
Thread t1 = new Thread(()->{
    for (;;) {
        try{
            Thread.sleep(1000);
            System.out.println("===");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});
t1.start();
// 10秒后 停止
Thread.sleep(10000);
// 停止
t1.stop();

很容易产生数据不一致 因为某一个事务或者一块代码没执行完的时候 就有可能被干掉

举个例子:

代码语言:txt
AI代码解释
复制
// lambda 表达式
Thread t1 = new Thread(()->{
    System.out.println("对象去洗澡了");
    try{
        System.out.println("钻被窝等着...");
        Thread.sleep(10000);
        System.out.println("洗白白 开小会");
    } catch (Exception e) {
        e.printStackTrace();
    }
});

t1.start();
// 10秒后 停止
Thread.sleep(5000);
// 停止
t1.stop();

结果:
对象去洗澡了
钻被窝等着...
    
可以看到哈,你等了半天,还没开始开小会就被打断了 。。  
3.3 suspend resume 被废弃了

suspend 让线程暂停

resume 让暂停的线程继续执行

suspend容易产生死锁等问题 如果忘记resume或者resume异常 那如果suspend的线程持有锁的话,就死锁了

代码语言:txt
AI代码解释
复制
public class TestDeamon03 {
    // 锁  表示对象
    public static Object obj = new Object();
    public static void main(String[] args) throws InterruptedException {

        // lambda 表达式
        Thread t1 = new Thread(()->{
                synchronized (obj){
                   try {
                       System.out.println("我出去打工了 留对象在家");
                       Thread.sleep(10000);
                       System.out.println("我回来了 娶我对象 ");
                   } catch (Exception e) {
                       e.printStackTrace();
                   }
                }
        });

        t1.start();
        // 2秒后 暂停
        Thread.sleep(2000);
        // 暂停
        t1.suspend();
        Thread.sleep(2000);
		// 恢复 
        resumeObj(t1);
    }

    // resume 模拟异常
    static void resumeObj(Thread t){
        int i = 1/0;
        t.resume();
    }
}

你找了个对象,把人家放家里,说打工1年回来娶,然后你回家途中找了个别人,一起幸福生活了,你对象在家...

被你占用,你又不通知、不释放

3.4 volatile 结束

volatile(保证内存可见)修饰一个变量 时间可能控制不是很精确 因为volatile修改了之后刷新到内存 在另一个线程读取到 还是需要时间的 虽然很快 但是一般的情况 都没什么问题

代码语言:txt
AI代码解释
复制
public class TestDeamon04 {
    static volatile boolean flag = true;
    public static void main(String[] args) throws InterruptedException {
        // lambda 表达式
        Thread t1 = new Thread(()->{
            int count =0;
            // flag == true 循环   flag==false 停止循环 也就结束线程了
            while (flag) {
                try {
                    Thread.sleep(1);
                    count++;
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            System.out.println("count:"+count);
        });

        t1.start();
        // 1秒后 停止
        Thread.sleep(1000);
        flag = false;
    }
}

多次输出结果:
    505、525、507、512 
可以看到每次输出结果是不确定的 ,
这种方式只能保证到达某个条件了就停止线程  
但是不能控制线程准确点停止 
比如你想让一个线程循环100次就停止 很难准确控制
3.5 interrupt 结束

也算标志位 但是比volatile高级一点 比如sleep、wait等操作会被中断

代码语言:txt
AI代码解释
复制
// lambda 表达式
final Thread t1 = new Thread(()->{
    int count =0;
    //
    while (!Thread.interrupted()) {
        try {
            count++;
        } catch (Exception e){
            e.printStackTrace();
        }
    }
    System.out.println("count:"+count);
});

t1.start();
// 1秒后 停止
Thread.sleep(1000);
t1.interrupt();

中断sleep测试:interrupt会中断sleep在异常捕获里边break就行了 而标志位flag是无法做到的

代码语言:txt
AI代码解释
复制
public class TestDeamon06 {
    static volatile boolean flag = true;
    public static void main(String[] args) throws InterruptedException {
        // lambda 表达式
        final Thread t1 = new Thread(()->{
            //
            while (!Thread.interrupted()) {
                try {
                    Thread.sleep(20000000);
                } catch (Exception e){
                    break;
                }
            }
            System.out.println("interrupted 结束 ");
        });

        // lambda 表达式
        final Thread t2 = new Thread(()->{
            while (flag) {
                try {
                    Thread.sleep(20000000);
                } catch (Exception e){
                    break;
                }
            }
            System.out.println("volatile-结束");
        });

        t1.start();
        t2.start();
        // 1秒后 停止
        Thread.sleep(1000);
        t1.interrupt();
        flag = false;
    }
}

总结:

stop 、suspend resume 已废弃

volatile标志位 无法中断sleep wait 等操作

interrupt 相当于标志位但是可以中断sleep wait等操作 捕获InterruptedException异常 进行线程结束

可能还有其他方式 大多数是基于标志位的

欢迎关注公众号:

公众号二维码.jpg
公众号二维码.jpg

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
LeetCode - 合并两个有序链表
原题地址:https://leetcode-cn.com/problems/merge-two-sorted-lists/
晓痴
2019/08/16
3910
LeetCode - 合并两个有序链表
LeetCode97|合并两个有序链表
这道题理解起来还是比较容易的对吧,两两比较,然后将较小的数据挂载dummyNode节点后面,这就是使用哨兵节点的好处,一般链表都或多或少的增加一个哨兵节点来处理数据。
码农王同学
2020/10/14
3160
LeetCode-21 合并两个有序链表
今天我们学习第21题合并两个有序链表,这是一道简单题。下面我们看看这道题的题目描述。
用户3470542
2019/06/26
3880
LeetCode-21 合并两个有序链表
《剑指offer》第21天:合并两个有序链表
首先我们拿到题目乍眼一看,类似这种链表的合并问题。基本上马上可以想到需要设置一个哨兵节点,这可以在最后让我们比较容易地返回合并后的链表。(不懂哨兵节点的同学,可以先移驾到 06.删除链表倒数第N个节点(19) 进行学习)
程序员小浩
2020/09/04
2450
leecode刷题(23)-- 合并两个有序链表
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
希希里之海
2019/05/14
4120
LeetCode-21-合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
benym
2022/07/14
1570
21. 合并两个有序链表
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
张伦聪zhangluncong
2022/10/26
1730
​LeetCode刷题实战21:合并两个有序链表
算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !
程序员小猿
2021/01/19
2620
剑指Offer LeetCode 面试题24. 反转链表
面试题24. 反转链表 定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
手撕代码八百里
2020/07/28
2820
LeetCode-面试题25-合并两个排序的链表
首先判断两个链表的值,小的头部赋值给MergeHead,然后进行下一步的递归判断,在合并的过程中可能出现链表长短不一的情况,如果l2链表为空返回l1剩下的头部,如果l1链表为空,返回l2剩下的头部
benym
2022/07/14
1530
面试官系列 - LeetCode链表知识点&题型总结
前段时间,写了面试必备的一系列文章,反应还不错。有一些读者反馈说,能不能整理一些面试常见的算法。前段时间,我恰好总结了 LeetCode 常见的面试算法题目。今天给大家分享一下。
程序员徐公
2022/01/20
6920
面试官系列 - LeetCode链表知识点&题型总结
leetcode链表之合并两个排序的链表
合并两个有序链表的基本思路就是设置一个cursor以及新链表的头指针,然后同时遍历两个链表,取小的节点作为cursor的next,然后该链表往前进,cursor也跟着往前进,最后再将cursor.next指向尚未遍历完的链表的剩余节点
code4it
2020/09/09
6640
leetcode链表之合并两个排序的链表
21 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
木瓜煲鸡脚
2021/01/18
3070
21 合并两个有序链表
LeetCode 21:合并两个有序链表 Merge Two Sorted Lists
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
爱写bug
2019/07/25
4170
LeetCode题解—两个有序链表合并
关于空间复杂度,有可能有的朋友会觉得用到了m+n长度的链表?所以空间复杂度也是O(m+n)?
码上积木
2021/02/08
2.2K0
LeetCode题解—两个有序链表合并
【日拱一卒】链表——两个有序的链表合并
思路就是挨个比较两个链表中的元素,谁更小就先取谁,然后记得将指针移到下一个节点,直到遍历完两个链表。
JackieZheng
2020/08/11
4530
【日拱一卒】链表——两个有序的链表合并
画解算法:21. 合并两个有序链表
https://leetcode-cn.com/problems/merge-two-sorted-lists/
灵魂画师牧码
2019/06/27
5680
画解算法:21. 合并两个有序链表
搞定大厂算法面试之leetcode精讲15.链表
搞定大厂算法面试之leetcode精讲15.链表 视频讲解(高效学习):点击学习 目录: 1.开篇介绍 2.时间空间复杂度 3.动态规划 4.贪心 5.二分查找 6.深度优先&广度优先 7.双指针 8.滑动窗口 9.位运算 10.递归&分治 11剪枝&回溯 12.堆 13.单调栈 14.排序算法 15.链表 16.set&map 17.栈 18.队列 19.数组 20.字符串 21.树 22.字典树 23.并查集 24.其他类型题 链表操作如下图: 动画过大,点击查看 时间复杂度: prepend: O(1
全栈潇晨
2021/12/02
4450
LeetCode 21. 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
freesan44
2020/06/08
2390
[剑指Offer]面试题25: 合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足递增有序的规则。
宇宙之一粟
2020/10/26
2270
推荐阅读
相关推荐
LeetCode - 合并两个有序链表
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档