java基础之多线程与Lambda表达式

一、Lambda表达式

Java从1.8以后引入了函数式编程,这是很大的一个改进。函数式编程的优点在提高编码的效率,增强代码的可读性。本文历时两个多月一点点写出来,即作为心得,亦作为交流。

1、无参和返回值

java基础之多线程与Lambda表达式_第1张图片
这样写非常的简单,其实就是简化我们的代码量,可以提供性能。

2、有且只能定义一个方法

java基础之多线程与Lambda表达式_第2张图片

3、有参实现

java基础之多线程与Lambda表达式_第3张图片

4、函数式接口

以上的接口必须是一个,java8出现了一个新的注解

  • 只能写一个方法
    java基础之多线程与Lambda表达式_第4张图片

6、default关键字的复习

java基础之多线程与Lambda表达式_第5张图片
java基础之多线程与Lambda表达式_第6张图片

二、java多线程

(一)线程概念

1、进程与线程

(1)进程概念

java基础之多线程与Lambda表达式_第7张图片
在这里插入图片描述
在这里插入图片描述
java基础之多线程与Lambda表达式_第8张图片
在这里插入图片描述
java基础之多线程与Lambda表达式_第9张图片

(2)线程概念

  • 举个例子康康
    java基础之多线程与Lambda表达式_第10张图片
    java基础之多线程与Lambda表达式_第11张图片

  • 进程与进程和进程与线程
    java基础之多线程与Lambda表达式_第12张图片

  • 所以得到概念为
    在这里插入图片描述

  • 看一下传统的进程使用资源情况
    java基础之多线程与Lambda表达式_第13张图片

  • 现代操作系统的情况
    在这里插入图片描述
    在这里插入图片描述
    查看CPU的一些信息
    java基础之多线程与Lambda表达式_第14张图片

java基础之多线程与Lambda表达式_第15张图片

(二)线程实现

1、多线程实现分析

在这里插入图片描述
java基础之多线程与Lambda表达式_第16张图片
java基础之多线程与Lambda表达式_第17张图片

1)Thread实现多线程

(1)概念部分

package java.lang.Thread,是jdk1.0就提供了。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)启动多线程

  • 看一下错误的调用
    java基础之多线程与Lambda表达式_第18张图片
    java基础之多线程与Lambda表达式_第19张图片
  • 看一下正确情况
    java基础之多线程与Lambda表达式_第20张图片
    java基础之多线程与Lambda表达式_第21张图片
  • 分析原因
    java基础之多线程与Lambda表达式_第22张图片
public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
         //有一个异常抛出,但是没有强制要求处理,因为该异常是RuntimeException
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }
private native void start0();
  • 异常分析
    java基础之多线程与Lambda表达式_第23张图片
    java基础之多线程与Lambda表达式_第24张图片
  • start0分析
    在这里插入图片描述
    java基础之多线程与Lambda表达式_第25张图片
  • 启动总结
    在这里插入图片描述

2)Runnable实现多线程

(1)看概念

在这里插入图片描述
package java.lang.Runnable
java基础之多线程与Lambda表达式_第26张图片
在这里插入图片描述

(2)实现多线程

  • 这样编写
    java基础之多线程与Lambda表达式_第27张图片

(3)分析此时多线程的启动(和Thread构造方法)

java基础之多线程与Lambda表达式_第28张图片
通过这里发现都是去调用了init方法,再去看init方法

java基础之多线程与Lambda表达式_第29张图片
java基础之多线程与Lambda表达式_第30张图片
在这里插入图片描述
java基础之多线程与Lambda表达式_第31张图片

(3)既然是函数式接口,那就Lambda上

java基础之多线程与Lambda表达式_第32张图片

3)Thread与Runnable之间的关系

(1)明白继承关系

public class Thread implements Runnable
java基础之多线程与Lambda表达式_第33张图片
java基础之多线程与Lambda表达式_第34张图片
在这里插入图片描述

  • 这样启动都是一个接口
    在这里插入图片描述
    java基础之多线程与Lambda表达式_第35张图片
    java基础之多线程与Lambda表达式_第36张图片
    使用Thread类也同样可以实现数据的共享
    在这里插入图片描述
    java基础之多线程与Lambda表达式_第37张图片
    在这里插入图片描述

(2)小总结

在这里插入图片描述

4)使用Callable实现多线程

它是在这个包下:import java.util.concurrent.*;

(1) 传统Runnable存在的问题

在这里插入图片描述
java基础之多线程与Lambda表达式_第38张图片
java基础之多线程与Lambda表达式_第39张图片

(2)看看callable接口

java基础之多线程与Lambda表达式_第40张图片
java基础之多线程与Lambda表达式_第41张图片

  • 来看看Future接口
    在这里插入图片描述
    java基础之多线程与Lambda表达式_第42张图片

(3)再来看继承关系

java基础之多线程与Lambda表达式_第43张图片

  • 再来看RunnableFuture的实现类
    java基础之多线程与Lambda表达式_第44张图片
    java基础之多线程与Lambda表达式_第45张图片
    在这里插入图片描述
  • 再来看继承关系
    java基础之多线程与Lambda表达式_第46张图片
    在这里插入图片描述

(4)Callable实现多线程

java基础之多线程与Lambda表达式_第47张图片
在这里插入图片描述

(三)多线程的操作

1)多线程的运行状态(生命周期)

其实就操作系统里面学的
在这里插入图片描述

(1)看图分析

java基础之多线程与Lambda表达式_第48张图片

(2)过程分析

java基础之多线程与Lambda表达式_第49张图片
在这里插入图片描述

2)线程命名和取得以及方法的使用

其实就是折腾Thread类的方法
在这里插入图片描述

(1)构造方法

public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }

    
    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

 
    Thread(Runnable target, AccessControlContext acc) {
        init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
    }

    
    public Thread(ThreadGroup group, Runnable target) {
        init(group, target, "Thread-" + nextThreadNum(), 0);
    }

    
    public Thread(String name) {
        init(null, null, name, 0);
    }

    
    public Thread(ThreadGroup group, String name) {
        init(group, null, name, 0);
    }

不详细介绍了

(2)获取线程名称

java基础之多线程与Lambda表达式_第50张图片
java基础之多线程与Lambda表达式_第51张图片

(3)设置或修改线程名称

java基础之多线程与Lambda表达式_第52张图片
java基础之多线程与Lambda表达式_第53张图片
强烈不建议这样进行修改操作
在这里插入图片描述

  • 当我们设置的名字的时候
    java基础之多线程与Lambda表达式_第54张图片

  • 当我们不进行手动设置名字的时候呢【为什么能自动编号呢】
    java基础之多线程与Lambda表达式_第55张图片
    原因其实就是如下
    java基础之多线程与Lambda表达式_第56张图片
    java基础之多线程与Lambda表达式_第57张图片
    java基础之多线程与Lambda表达式_第58张图片

  • 观察线程的获取
    在这里插入图片描述
    java基础之多线程与Lambda表达式_第59张图片
    在这里插入图片描述
    java基础之多线程与Lambda表达式_第60张图片
    在这里插入图片描述

  • 进程分析
    经过分析可以发现,都在看各个线程的概念,咱们程序的核心问题,所有的线程都是在进程里面创建的,那进程在哪里呢?答案其实很简单,每当java命令运行一个类的时候就会在操作系统的内部为其分配一个进程,而现在所有的程序执行的时候都是基于线程的方式运行的,其中会由JVM帮助用户手工创建一个主线程(main),而后再由主线程创建若干个线程。
    java基础之多线程与Lambda表达式_第61张图片

(4)线程休眠

  • 看一下方法
    在这里插入图片描述
    java基础之多线程与Lambda表达式_第62张图片
    java基础之多线程与Lambda表达式_第63张图片

  • 看一下异常继承关系
    java基础之多线程与Lambda表达式_第64张图片
    在这里插入图片描述

  • 线程休眠【如下处理就感觉线程A和B是一起执行的一样,这是为什么呢】
    java基础之多线程与Lambda表达式_第65张图片
    java基础之多线程与Lambda表达式_第66张图片
    在这里插入图片描述

(5)线程中断

  • 看点概念
    在这里插入图片描述
    java基础之多线程与Lambda表达式_第67张图片
  • 它有如下的一些方法
    java基础之多线程与Lambda表达式_第68张图片

(5)线程的强制执行

在这里插入图片描述
正常情况下我们是多个线程在竞争去抢夺,但是有特殊情况下,某个线程会强制抢夺。
java基础之多线程与Lambda表达式_第69张图片

public class MyThread {
    public static void main(String[] args) throws InterruptedException {
        Thread mainThread = Thread.currentThread();
        Thread joinThread = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                if (i > 10) {

                    try {
                        Thread.sleep(1000);
                        //只要满足i>10那就要把所有的资源交给主线程处理
                        mainThread.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + "子线程");
            }
        },"线程A");

        joinThread.start();
        for (int i = 0; i < 1000; i++) {
            Thread.sleep(1000);
            System.out.println("当前主线程" + mainThread);
        }
    }




}

(6)线程礼让

在这里插入图片描述

  • 像这样的话就感觉差不多是交替执行的【仅仅是感觉】
    java基础之多线程与Lambda表达式_第70张图片
  • 礼让情况
    java基础之多线程与Lambda表达式_第71张图片
public class MyThread {
    public static void main(String[] args) throws InterruptedException {
        Thread mainThread = Thread.currentThread();
        Thread joinThread = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                try {
                    if ( i % 2 == 0) {
                        Thread.yield();
                        System.out.println("应该是礼让线程执行");
                    }
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName() + "子线程");
                } catch (Exception e) {

                }
            }
        },"线程A");

        joinThread.start();
        for (int i = 0; i < 1000; i++) {
            Thread.sleep(1000);
            System.out.println("当前主线程" + mainThread);
        }
    }




}

(7)线程优先级

java基础之多线程与Lambda表达式_第72张图片

  • 首先模拟三个线程执行
    java基础之多线程与Lambda表达式_第73张图片
  • 主方法(主线程)决定了子线程的优先级
    java基础之多线程与Lambda表达式_第74张图片
  • 优先是可以修改的,在线程启动之前。【你设置了也不起什么卵用】
    java基础之多线程与Lambda表达式_第75张图片
    在这里插入图片描述
    优先级高的,有可能先执行,仅仅是有可能。

(四)线程同步与死锁

1、同步问题

1)问题的引入

多线程的引入是在为了能在尽可能的提高效率,但是操作不当是会出现问题的。

  • 创建5个线程进行卖票处理
    java基础之多线程与Lambda表达式_第76张图片
    并不是加入了延迟才会出现这个问题,仅仅是更加明显而已。
    java基础之多线程与Lambda表达式_第77张图片
    能让问题更加明显的原因是我们线程休眠正好处于了修改和检查的期间,所以更加明显。
    java基础之多线程与Lambda表达式_第78张图片
    当最后一张票被5个线程抢着了,同时对原来的数据进行减1,那就会出现了这个了。

2)线程同步处理

java基础之多线程与Lambda表达式_第79张图片
在这里插入图片描述

(1)使用同步代码块来解决

  • 可以采用synchronized(同步对象) {业务逻辑}
    在这里插入图片描述
    java基础之多线程与Lambda表达式_第80张图片
  • 也可以这样写
class Thread1 implements Runnable  {

    private Integer ticket = 5;

    @Override
    public void run() {//线程运行的主方法
        synchronized(this) {
            while (true) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "正在卖票" + "当前剩余票数" + (--ticket));
                } else {
                    break;
                }
            }
        }
    }
}

public class MyThread {
    public static  int ticket = 5;
    public static void main(String[] args) throws InterruptedException {
        Thread1 thread1 = new Thread1();

        for (int i = 0; i < 5; i++) {
            new Thread(thread1,"售票机" + i).start();
        }
    }
}

在这里插入图片描述

(2)使用同步方法实现

java基础之多线程与Lambda表达式_第81张图片

public class MyThread {
    public static  int ticket = 5;
    public static void main(String[] args) throws InterruptedException {
        Thread1 thread1 = new Thread1();

        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                hello();
            },"售票机" + i).start();
        }
    }

    public static synchronized boolean hello() {
        while (true) {
            if (ticket > 0) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "正在卖票" + "当前剩余票数" + (--ticket));
                return true;
            } else {
                return false;
            }
        }
    }
}

2、线程死锁

java基础之多线程与Lambda表达式_第82张图片


class Book {//描述的书资源

}

class Paint {//描述回话资源

}

public class LockTest {

    public static void main(String[] args) {
        Book book = new Book();
        Paint paint = new Paint();

        Thread threadA = new Thread(() -> {
            synchronized(book) {
                System.out.println("A对B说,你借给我回话资源,我再给你书资源");
                try {
                    Thread.sleep(10000);
                    //现在A要锁paint资源
                    synchronized(paint) {
                        System.out.println("A得到了回话资源");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"线程A");
        Thread threadB = new Thread(() -> {
            synchronized(paint) {
                System.out.println("B对A说,你借给我书资源,我再给你回话资源");
                try {
                    Thread.sleep(10000);
                    //现在A要锁paint资源
                    synchronized(book) {
                        System.out.println("B得到了书资源");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"线程B");

        threadA.start();
        threadB.start();
    }
}

java基础之多线程与Lambda表达式_第83张图片
在这里插入图片描述
只有用点工具进行监控,现实生活中很难预测。

  • 结论:多个线程更新同一资源的时候必须考虑到同步,而且同步所带来的问题就是线程的死锁。

3、生产者和消费者

1)生产者和消费者模型

(1)看概念

在这里插入图片描述
java基础之多线程与Lambda表达式_第84张图片
java基础之多线程与Lambda表达式_第85张图片

(2)类结构分析

java基础之多线程与Lambda表达式_第86张图片
java基础之多线程与Lambda表达式_第87张图片

2)代码操作模型

(1)代码实现

class Message {
    private String title;
    private String content;

    public Message(String title,String content) {
        this.title = title;
        this.content= content;
    }

    public Message() {

    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public String getTitle() {
        return title;
    }

}

class Producer implements Runnable {

    Message message;

    public Producer(Message message) {
        this.message = message;
    }

    @Override
    public void run() {

        try {
            for (int i = 0; i < 50; i++) {//生成50个产品
                if (i % 2 == 0) {
                    message.setTitle("你");
                    Thread.sleep(1000);
                    message.setContent("好");
                } else {
                    message.setTitle("不");
                    Thread.sleep(1000);
                    message.setContent("hao");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


class Consumer implements Runnable {

    Message message;

    public Consumer(Message message) {
        this.message = message;
    }

    @Override
    public void run() {
        try {
            for (int i = 0; i < 50; i++) {
                System.out.println("消费者 title" + this.message.getTitle() + "content = " + this.message.getContent());
                Thread.sleep(1000);
            }
        } catch (Exception e) {

        }
    }
}

public class mainClass {

    public static void main(String[] args) {
        Message message = new Message();
        new Thread(new Producer(message)).start();
        new Thread(new Consumer(message)).start();
    }
}

  • 观察结果
    java基础之多线程与Lambda表达式_第88张图片
    java基础之多线程与Lambda表达式_第89张图片
    这些问题并不是加上sleep才会出现问题的,仅仅是我们现在电脑比价牛逼,不加sleep很少出现问题。

(2)类结构分析

在这里插入图片描述

(3)解决数据同步问题

在这里插入图片描述

  • 问题分析
    java基础之多线程与Lambda表达式_第90张图片
  • 代码实现
package cn.mldn.Juc.producerAndcustomer;

class Message {
    private String title;
    private String content;

    public Message(String title,String content) {
        this.title = title;
        this.content= content;
    }

    public Message() {

    }

    public synchronized void setContentAndsetTitle(String content,String title) {
        this.content = content;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.title = title;
    }


    public synchronized String GetString() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "Message{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                '}';
    }
}

class Producer implements Runnable {

    Message message;

    public Producer(Message message) {
        this.message = message;
    }

    @Override
    public void run() {

        try {
            for (int i = 0; i < 50; i++) {//生成50个产品
                if (i % 2 == 0) {
                    message.setContentAndsetTitle("绝地","求生");
                    Thread.sleep(10000);
                } else {
                    message.setContentAndsetTitle("王者","荣耀");
                    Thread.sleep(1000);

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


class Consumer implements Runnable {

    Message message;

    public Consumer(Message message) {
        this.message = message;
    }

    @Override
    public void run() {
        try {
            for (int i = 0; i < 50; i++) {
                System.out.println(this.message.GetString());
                Thread.sleep(1000);
            }
        } catch (Exception e) {

        }
    }
}

public class mainClass {

    public static void main(String[] args) {
        Message message = new Message();
        new Thread(new Producer(message)).start();
        new Thread(new Consumer(message)).start();
    }
}

  • 看结果分析:有重复生产和重复消费
    java基础之多线程与Lambda表达式_第91张图片

(4)解决线程重复操作问题

  • 问题分析和方法学习
    java基础之多线程与Lambda表达式_第92张图片
    java基础之多线程与Lambda表达式_第93张图片
    在这里插入图片描述
    显示肯定不用这种来处理,具体的可以学习JUC内容

  • 代码实现

class Message {
    private String title;
    private String content;

    boolean flag = true;//等于true为可以生产,不可以消费。为false,可以消费,不可以生产
    public Message(String title,String content) {

        this.title = title;
        this.content= content;
    }

    public Message() {

    }

    public synchronized void setContentAndsetTitle(String content,String title) {


        if (this.flag == false) {
            try {
                //说明有消费者线程在执行,等消费者线程执行完毕后唤醒
                super.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.content = content;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.title = title;

        //生产完成后,把消费者线程唤醒
        this.flag = false;
        super.notify();//唤醒其他线程
    }


    public synchronized String GetString() {
        if (flag == true) {
            try {
                //说明生产者线程在执行,等待生成完成后被唤醒
                super.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //消费完成后,把生产者线程唤醒
        this.flag = true;
        super.notify();
        return "Message{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                '}';

    }
}

class Producer implements Runnable {

    Message message;

    public Producer(Message message) {
        this.message = message;
    }

    @Override
    public void run() {

        try {
            for (int i = 0; i < 50; i++) {//生成50个产品
                if (i % 2 == 0) {
                    message.setContentAndsetTitle("绝地","求生");
                    Thread.sleep(1000);
                } else {
                    message.setContentAndsetTitle("王者","荣耀");
                    Thread.sleep(1000);

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


class Consumer implements Runnable {

    Message message;

    public Consumer(Message message) {
        this.message = message;
    }

    @Override
    public void run() {
        try {
            for (int i = 0; i < 50; i++) {
                System.out.println(this.message.GetString());
                Thread.sleep(1000);
            }
        } catch (Exception e) {

        }
    }
}

public class mainClass {

    public static void main(String[] args) {
        Message message = new Message();
        new Thread(new Producer(message)).start();
        new Thread(new Consumer(message)).start();
    }
}

  • 观察结果
    java基础之多线程与Lambda表达式_第94张图片

3)优雅的停止线程

在这里插入图片描述
java基础之多线程与Lambda表达式_第95张图片
在这里插入图片描述

  • 停止多线程
    java基础之多线程与Lambda表达式_第96张图片
    java基础之多线程与Lambda表达式_第97张图片

(五)线程相关其他知识

1、守护线程

  • 概念
    在这里插入图片描述

  • 常用方法
    在这里插入图片描述

  • 代码观察

package cn.mldn.Juc.class1;

class Message implements Runnable {

    public Message() {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("守护线程执行");
            }
        });
        thread.setDaemon(true);//设置Thread线程为守护线程
        thread.start();
    }

    @Override
    public void run() {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("当前线程执行" + Thread.currentThread().getName() + "执行");
        }
    }
}

public class WatchThread {

    public static void main(String[] args) {
        new Thread(new Message()).start();
    }
}

  • 案例分析
    在这里插入图片描述
    java基础之多线程与Lambda表达式_第98张图片

2、volatile关键字

在这里插入图片描述

  • 观察代码和结果
package cn.mldn.Juc.class1;

class Message implements Runnable {


    private volatile int ticket = 3;

    @Override
    public void run() {
        while (true) {
            if (ticket > 0) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("剩余票数位" + (--this.ticket));
            } else {
                break;
            }
        }
    }
}

public class WatchThread {

    public static void main(String[] args) {
        Message message = new Message();
        new Thread(message,"机器A").start();
        new Thread(message,"机器B").start();
    }
}

java基础之多线程与Lambda表达式_第99张图片

  • 那既然它实现不了同步,那这关键字有什么用呢?
    java基础之多线程与Lambda表达式_第100张图片
    在这里插入图片描述

  • volatile正确使用格式

package cn.mldn.Juc.class1;

class Message implements Runnable {


    private volatile int ticket = 3;

    @Override
    public void run() {
        while (sale()) {

        }
    }


    public synchronized boolean sale() {
        if (ticket > 0) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("剩余票数位" + (--this.ticket));
            return true;
        } else {
            return false;
        }
    }
}

public class WatchThread {

    public static void main(String[] args) {
        Message message = new Message();
        new Thread(message,"机器A").start();
        new Thread(message,"机器B").start();
    }
}

在这里插入图片描述

3、线程加减面试题

  • 问题是:设计4个线程,两个实现加操作,另外两个实现减操作。
package cn.mldn.Juc.class1;

class Message1  {
    private int number = 0;

    public synchronized void add() {
        //1判断
        while (number == 0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //2干活
        number++;
        System.out.println(Thread.currentThread().getName() + "完成工作" + number);

        //3通知
        this.notifyAll();
    }

    public synchronized void sub() {
        //1判断
        while (number != 0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //2干活
        number--;
        System.out.println(Thread.currentThread().getName() + "完成工作" + number);

        //3通知
        this.notifyAll();
    }
}


public class InterviewTest {
    public static void main(String[] args) {
        Message1 message = new Message1();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                message.add();
            }
        },"一号加法线程").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                message.add();
            }
        },"二号加法线程").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                message.sub();
            }
        },"三号减法线程").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                message.sub();
            }
        },"四号减法线程").start();
    }
}

4、电脑生产面试题

在这里插入图片描述
java基础之多线程与Lambda表达式_第101张图片

package cn.mldn.Juc.class1;

class Computer  {
    private String brand;//电脑品牌
    private double price;//电脑价格

    public Computer(String brand,double price) {
        this.brand = brand;
        this.price = price;
    }

    @Override
    public String toString() {
        return "Computer{" +
                ":品牌=" + brand + '\'' +
                ":价格=" + price +
                '}';
    }
}

class Resource {
    private int number = 0;//公共资源电脑数量
    private Computer computer = null;//当前电脑
    public Resource() {
        Thread numberDaemonThread = new Thread(() ->{
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("后台统计线程在统计电脑,当前生产电脑数量为= " + this.number);
            }

        });
        numberDaemonThread.setDaemon(true);
        numberDaemonThread.start();
    }

    public synchronized void create(String brand,double price) {
        //首先判断(如果为空,等待消费
        while (this.computer != null) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //干活
        this.computer = new Computer(brand,price);
        this.number ++;
        System.out.println("" + Thread.currentThread().getName() + "完成电脑生产完成");
        //通知我生产好啦
        this.notifyAll();

    }

    public synchronized void decreate() {
        //首先判断(如果为空,等待生产
        while (this.computer == null) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //干活
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("" + Thread.currentThread().getName() + "完成搬运");
        this.computer = null;
        //通知我生产好啦
        this.notifyAll();

    }
}

public class ComputerTest {
    public static void main(String[] args) {
        Resource resource = new Resource();
        new Thread(() -> {
            for (int i = 0; i < 50; i++) {
                if (i % 2 == 0) {
                    resource.create("惠普",6000.00);
                } else {

                }
            }
        },"生产线程").start();

        new Thread(() -> {
            for (int i = 0; i < 50; i++) {
                if (i % 2 == 0) {
                    resource.decreate();
                } else {

                }
            }
        },"搬运线程").start();
    }
}

5、竞拍抢答面试题

在这里插入图片描述

package cn.mldn.Juc.class1;


import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

class Resource1 implements Callable {
    private boolean flag;//抢答结果状态

    @Override
    public String call() throws Exception {
        Thread.sleep(1000);

        //由于我们要每个线程进行先后执行
        synchronized(this) {
            if (this.flag == false) {
                this.flag = true;
                return Thread.currentThread().getName() + "抢答成功";
            } else {
                return Thread.currentThread().getName() + "抢答失败";
            }
        }
    }
}

public class CallableInterview {
    public static void main(String[] args) {
        Resource1 resource = new Resource1();
        FutureTask futureTask = new FutureTask<>(resource);
        FutureTask futureTask1 = new FutureTask<>(resource);
        FutureTask futureTask2 = new FutureTask<>(resource);
        new Thread(futureTask,"抢答人A").start();

        new Thread(futureTask1,"抢答人B").start();

        new Thread(futureTask2,"抢答人C").start();
    }
}

三、最后补充一下JUCSaleTicket

1、概念

并发:多个线程去抢占同一个资源
并行:两件事情同时进行【你在看视频和做笔记】

2、JUC的三个包

java.util.concurrent
java.util.concurrent.atomic
java.util.concurrent.locks

3、如何编写企业家多线程

在高内聚低耦合的前提下,线程,操作,资源类

1)Lock介绍

  • 首先说说为什么需要Lock
    我们实现同步第一想到的应该都是synchronized加到方法或者方法的内部实现同步,以实现数据的唯一性,但是它是重量级的,一旦锁了就把整个方法都锁住了(这样可以把synchronized加到方法内,以实现数据的共享而不出问题),但是synchronized是比较重量级的,锁就把内部完全给锁住了并发性就不行了,重量级了不行。所以就会有了Lock来处理。Lock可以实现可重复锁,性能更高效。
    java基础之多线程与Lambda表达式_第102张图片

(1)实现30张卖票程序分析

  • 来看一下Lock的莫办
    java基础之多线程与Lambda表达式_第103张图片
  • 看看代码
package cn.mldn.Juc.class2;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

public class SaleTicket {

    public static void main(String[] args) {

            //在高内聚低耦合的前提下(其实就是一个类,如果想去操作,必须去通过方法去调用)
        //1、先创建资源类(在高内聚低耦合的前提下)
        Ticket ticket = new Ticket();
        //2、创建线程 3、操作
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            }
        },"线程1").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            }
        },"线程2").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            }
        },"线程3").start();
    }
}

class Ticket {//资源类就是一个类[内聚就是要聚变量]

    private int number = 30;
    Lock lock = new ReentrantLock();

    public  void sale() {
        lock.lock();
        try {
            if (number > 0) {
                System.out.println(Thread.currentThread().getName() + "卖出" + (number --) + "还剩下:" + number);
            }
        } catch (Exception e) {

        } finally {
            lock.unlock();
        }
    }


}
  • 看看简洁版
public class SaleTicket {

    public static void main(String[] args) {

            //在高内聚低耦合的前提下(其实就是一个类,如果想去操作,必须去通过方法去调用)
        //1、先创建资源类(在高内聚低耦合的前提下)
        Ticket ticket = new Ticket();
        //2、创建线程 3、操作
        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        },"线程3").start();

        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        },"线程2").start();

        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        },"线程1").start();
    }
}

class Ticket {//资源类就是一个类[内聚就是要聚变量]

    private int number = 30;
    Lock lock = new ReentrantLock();

    public  void sale() {
        lock.lock();
        try {
            if (number > 0) {
                System.out.println(Thread.currentThread().getName() + "卖出" + (number --) + "还剩下:" + number);
            }
        } catch (Exception e) {

        } finally {
            lock.unlock();
        }
    }


}

你可能感兴趣的:(Java相关笔记,Lambda,java,多线程)