Java学习---异常与多线程(二)

Java学习---异常与多线程

线程间通信

多个线程在处理同一资源,但处理的动作不同,如若线程之间没有通信,各自处理各自的,就会发生异常。比如一个做包子的和一个买包子的人,做包子的不能不管买包子的人数,卖包子的不能不管有没有包子,两者之间需要通信。理解这个后,我们就来说说为什么要处理线程间通信的问题。
为什么要处理线程间通信
多个线程并发执行时,在默认的情况下CPU是随机切换线程的,当我们需要多个线程来共同完成一件任务,并且我们希望他们有规律的执行,那么多线程之间需要一些协议通信,以此来帮助我们达到多线程共同操作一份数据,而这个协议通信就是等待与唤醒机制。
等待与唤醒机制
在前面我们谈到了锁,多个线程之间可以通过竞争锁来达到线程的有序执行,但这并不能满足所有需求。接下来介绍几种Object类中的方法。
wait()线程进入无限等待状态
notify()唤醒等待中的线程
notifyAll()唤醒所有等待中的线程
注意:操作wait()和notify()的锁对象一定要相同、
在这里插入图片描述
下面的代码是用匿名内部内实现的,并没有创建单独的类去实现,因此在我不能更改

public class Main{
    public static void main(String[] args) {
            boolean judge = false;/*因为匿名内部类传的内部变量的值是不能变的
           所以这里的判断其实就充当一个规范顺序的东西。*/
        Object obj=new Object();//所对象
        new Thread(new Runnable() {//吃包子线程。这里也可以写Lambda表达式,会更简单
            @Override
            public void run() {
                System.out.println("我想吃包子");
                synchronized (obj){
                    if (judge ==false){//false就是没有包子,需要等待做包子
                        try {
                            obj.wait();//进入等待
                            //注意这里可能会有异常抛出,在synchronized里只能用try...catch
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("好吃");
                }
            }
        }).start();
        new Thread(new Runnable() {//做包子线程
            @Override
            public void run() {
                synchronized (obj){
                    if (judge ==true){
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("包子做完了,给你吃");
                    obj.notify();
                }
            }
        }).start();

    }
}

线程池

一个线程的创建与销毁是很费时间的,我们前面创建的线程并不能长久保存,当CPU处理完后就会对该线程进行销毁,占用资源。
线程池就是可以重复使用的多个线程的集合,可以一直存在。

注意:有线程池的代码在执行过程中不会自己直接结束。
在这里插入图片描述
线程池的使用:

线程池类Executors,与线程有关的类
创建线程池:

/*Executors中有一个静态方法newFixedThreadPool,返回值类型是
ExecutorService,而ExecutorService是线程池接口的实现类,
可以调用start方法开启线程
线程池的操作方法:
   submit(Runnable task)提交一个Runnable任务用于执行
   shutdown()销毁线程池,一般不建议操作
*/
ExecutorService executor=Executors.newFixedThreadPool(3);//创建3个线程
    p.submit(()->{//注意这里是Runnable而不是Thread
        System.out.println(Thread.currentThread().getName());
    });

Lambda表达式

当需要重写方法时,需要写许多冗长的代码,用Lambda表达式可以简化这个步骤。注意:Lambda表达式是一个闭包,内部类中重写方法时可以用。大大简化了代码的书写。
Lambda表达式是函数式编程的一个重要体现,就是说我不用管它是怎么运行的,只要知道它可以完成某种功能就可以了。因此不需要访问内部的结构与变量。由此可知,外部类不可以不能访问Lambda表达式。
格式:
()->{方法体}()

new Thread(new Runnable() {//正常写的代码
    @Override
    public void run() {
       System.out.println(Thread.currentThread().getName());
       }
    });


    new Thread(()->{//用Lambda表达式写的代码
       System.out.println(Thread.currentThread().getName());
    }).start();

这样一看就能够发现问题了,Lambda表达式确实省去了不少功夫。

在表达式中也可以有参数和返回值。

注意:Lambda表达式是可推导、可省略的。因此,必须有接口,且接口中只有一个抽象方法时才能使用Lambda表达式。
可省略的:凡是可以推导的都可以省略。
1、(参数列表)–>括号中参数列表的数据类型可以省略不写;如果参数列表只有一个,那么类型和()都可以不写。
2、{一些代码}–>如果{}中的代码只有一行,那么就可以省略{}、return和" ; "(注意要省略就一起省略)

public class Person {
    public static void main(String[] args) {
        int c=getSum(10,20,(int a,int b)->{
            return a+b;
        });
        System.out.println(c);
        int d=getSum(10,20,(a,b)->a+b);//要省就都省
        System.out.println(d);
    }
    public static int getSum(int a,int b,P p){
        return p.sum(a,b);
    }
}
interface P{//接口中只有一个抽象方法时才能使用Lambda表达式
    public int sum(int a,int b);
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值