线程学习之进阶知识补充

举报
多米诺的古牌 发表于 2021/08/25 22:59:09 2021/08/25
【摘要】 1.实现线程的方法1.1 创建线程类,直接new Thread();1.2 通过Runable接口实现,是通过实现Runable接口类传入new Thread()中,new Thread(new Runable(){...});1.3 通过Callable接口实现,new Thread(new FutrueTask(new Callable(){...})),因为Thread线程类的构造器只...

1.实现线程的方法

1.1 创建线程类,直接new Thread();

1.2 通过Runable接口实现,是通过实现Runable接口类传入new Thread()中,new Thread(new Runable(){...});

1.3 通过Callable接口实现,new Thread(new FutrueTask(new Callable(){...})),因为Thread线程类的构造器只和Runable接口有关,那么要怎么通过Callable接口去实现呢?

通过查看Runable相关实现类,我们可以发现一个神奇的实现类FutrueTask实现类,在FutrueTask实现类的构造器中是可以传Callable接口的,这样通过借助FutureTask实现类的构造器我们就可以实现Callable接口的线程实现方法了。

2.Runable接口和Callbale接口实现线程的区别

Runable接口作为Thread线程类唯一准入参数,得天独厚的条件,为什么还要费劲的找中间商去使用Callable接口实现线程的创建呢?

2.1 Callable接口和Runable接口的区别

2.1.1 可以有返回值;

2.1.2 可以抛出异常;

2.1.3 Callable接口中的抽象方法是V call(),而V也是Callable接口是泛型;而Runable接口的抽象方法是void run();

注1:在获取Callable接口的抽象类的重写后的返回值,是通过get()方法获取的,但是存在一个问题是,这样在call方法中处理比较复杂的逻辑时,可以造成线程的阻塞,可以通过将获取返回值的操作放在最后或者通过异步通信的方式来进行处理。

注2:在多个线程执行同一个Callable接口时,会出现缓存的效果,可以用来提高效率,即不同线程调用同一个call()的时候,只会执行一遍;原理是JV,在第二次调用FutrueTask对象所持有的线程的时候,FutrueTask的state状态此时已经不是NEW状态,此时会直接结束对应的线程,导致任务不执行。

3.常用的同步辅助类

3.1 CountDownLatch 减法计数器

3.1.1 核心方法countDown();数量-1的方法,需要提前设定好总的线程个数;

3.1.2 await()方法,用于等待计数器归零,然后再执行下面的操作,即线程调用countDown()方法进行-1后,当计数器归为0的时候,就会被await()方法进行唤醒,继续后续的业务操作。

3.2 CyclicBarrier 加法计数器

3.2.1 加法计数器的构造器是CyclicBarrier(int i,Runable run),需要先设定一个数字,并且可以再设定一个达到这个计数后需要执行的线程;

3.2.2 await方法,再设定好的CyclicBarrier加法计数器后,达到条件时,就会通过await方法进行唤醒设置达到计数后需要执行的线程,然后会执行await方法后的操作,比如下面代码中打印方法,在阻塞被唤醒后会不按顺序的执行7次;

CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
        System.out.println("完成任务,执行成功!");
    });

    for (int i = 1; i <= 7 ; i++) {
        int temp = i;
        new Thread(()->{
            try {
                System.out.println(Thread.currentThread().getName()+"+1后累计到"+temp+"次");
                cyclicBarrier.await();
                System.out.println("这时候await方法执行结束了!"+ Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

执行结果如下:

Thread-0+1后累计到1次
Thread-1+1后累计到2次
Thread-2+1后累计到3次
Thread-3+1后累计到4次
Thread-4+1后累计到5次
Thread-5+1后累计到6次
Thread-6+1后累计到7次
完成任务,执行成功!

这时候await方法执行结束了!Thread-6
这时候await方法执行结束了!Thread-1
这时候await方法执行结束了!Thread-3
这时候await方法执行结束了!Thread-2
这时候await方法执行结束了!Thread-5
这时候await方法执行结束了!Thread-0
这时候await方法执行结束了!Thread-4

Process finished with exit code 0

3.3 Semaphore 信号量标识

3.3.1 可以用来控制流量,保证体系内只有多少的数量线程执行,然后当里面的线程结束后释放完毕,会放入同等数量的线程进行补充,始终保持设定的信号数量;

3.3.2 主要可以应用于限流等地方;

3.3.3 acquire()方法,在设置好Semaphore的初始储量后,获得一个资源,然后等待被释放;

3.3.4 release()方法,进行释放一个资源的操作,并且释放后悔唤醒等待的线程;

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。