线程—并发编程(3)

线程—并发编程(基础+2)



一、线程之间的相互控制

提示:这一部分是接着上一篇继续展开的哈哈哈:

1、Thread.yield()方法

线程让步:使用该方法的线程从运行态切换到就就绪状态(只是放弃了CPU,没有等待外部条件),此时该线程随时可以被调度回CPU。
举个例子看一下吧👇👇👇👇👇👇

public class MethodYield {
    public static void main(String[] args) {
        PrintWhoAmI why=new PrintWhoAmI("魏神么");
        PrintWhoAmI eat=new PrintWhoAmI("不吃饭");
        why.start();
        eat.start();
    }
}
class PrintWhoAmI extends Thread{
    public String name;
    PrintWhoAmI(String name){
        this.name=name;
    }
    @Override
    public void run() {
        while(true){
            System.out.println("本小姐是"+name);
//            if(name.equals("魏神么")){
//                Thread.yield();
//            }
        }
    }
}

此时,who和eat两个线程并发执行,输出内容的概率和频率大致相等,但是,加上yield()方法之后(就是上面代码中注释掉的那几条语句),why线程调用yield()方法,所以该线程做出让步,主动放弃CPU,“魏神么”的输出次数远远小于“不吃饭”。

那么,什么时候会用到yield()方法呢?
yield()方法主要用于执行一些耗时较久的计算任务,为了防止计算机处于“卡顿”的现象,时不时的让出CPU这个宝贵资源,给操作系统的其他进程用(来干点别的活儿)。

2、停止线程的相关方法

B线程正在赶别的事,但发生了一些突发情况,A线程需要叫B线程来帮他干点别的事儿,此时A线程就需要通知B线程停下来手头正在忙的事情来帮助他。

(1)Thread.stop()方法

暴力法停止,不管被停止的线程工作到了哪一步,直接干掉希望停止的线程。但是这种方法太暴力了,所以这个方法就不咋用了。

(2)Thread.interrupt()方法

一种优雅的方式来停止希望停止的线程。要停止B线程,就与B线程进行协商,比较温柔。众所周知,interrupt是中断的意思,实际上并不会影响B线程的运行,而是给B线程发送一个消息(设置了一个停止标志)。那么问题来了,B线程是怎么感知到有人让他停止呢?
分情况讨论:

  1. B线程处于运行状态:可以通过 interrupted() 方法来判断是否有人让他停止。返回true:有人让他停止;返回false:没人让他停止。(至于B要不要停止,完全是代码控制的)
  2. B线程处于休眠状态(sleep,join……):这就意味着B无法立即执行 interrupted() 方法,此时JVM的处理方式是以异常形式通知B(InterruptedException)。当B处于休眠状态时,捕获了 InterruptedException 异常,代表有人让B线程停止,具体要不要停、什么时候停、怎么停,完全看自己。
throws InterruptedException

二、应用线程的场景

1.计算密集型任务

在计算密集型任务中,应用多线程,可以提高计算效率、提升整体速度。

2.执行流阻塞(最常见的场景)

当其中某个执行流阻塞时,为了能够还能继续处理其他业务,可以应用线程。
既然这个场景非常常见,那就举个例子吧💁‍♀️
以斐波那契数为例:
普通方法:

//这是普通的求斐波那契数的程序,有多组输入
//但有个缺点,如果用户输入的数字过大,程序就会产生类似于阻塞的现象,此时,也就无法计算下一个输入,这种情况就可以应用线程。
public class NoUseThread {
    static long fib(int n){
        if(n==0||n==1){
            return 1;
        }
        return fib(n-1)+fib(n-2);
    }
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        while(scanner.hasNextInt()){
            int n=scanner.nextInt();
            long ret=fib(n);
            System.out.printf("fib(%d)=%d",n,ret);
            System.out.println();
        }
    }
}


应用线程:

public class useThread {
    static long fib(int n){
        if(n==0||n==1){
            return 1;
        }
        return fib(n-1)+fib(n-2);
    }
    static class threadOfFib extends Thread{
        int n;
        threadOfFib(int n){
            this.n=n;
        }
        @Override
        public void run() {
            long ret=fib(n);
            System.out.printf("fib(%d)=%d",n,ret);
            System.out.println();
        }
    }
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        while(scanner.hasNextInt()){
            int n=scanner.nextInt();
            threadOfFib th=new threadOfFib(n);
            th.start();
        }
    }
}

利用线程求斐波那契
应用线程之后,当用户输入较大的数字,程序出现“阻塞”现象,但完全不影响程序继续处理用户之后输入的数字。
哈哈哈线程真好用🙆‍♀️

三、线程基本知识总结

1、什么是线程?

代表一个独立的执行流,属于某个进程,是CPU进行调度、分配CPU资源的基本单位。

2、OS为什么要引入线程?

分离进程的两个任务,即分配资源的基本单位(进程) ➕ 调度的基本单位(线程)。

3、什么场景会用到多线程?

  • 计算密集型任务时,应用线程可以提高效率;
  • 可能发生阻塞的场景时,应用多线程,不会影响别的工作的正常运行。

4、线程在Java中使用

  • Thread对象和Runnable对象理解(注意用法);
  • id、name、优先级、状态、前后台线程……;
  • 启动线程、停止线程、等待停止……;
  • 休眠、线程让步……

总结

线程的基础知识,就到这里啦,拜拜的🤗

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值