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

一、Lambda表达式

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

1、无参和返回值

在这里插入图片描述
这样写非常的简单,其实就是简化我们的代码量,可以提供性能。

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

在这里插入图片描述

3、有参实现

在这里插入图片描述

4、函数式接口

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

  • 只能写一个方法
    在这里插入图片描述

6、default关键字的复习

在这里插入图片描述
在这里插入图片描述

二、java多线程

(一)线程概念

1、进程与线程

(1)进程概念

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)线程概念

  • 举个例子康康
    在这里插入图片描述
    在这里插入图片描述

  • 进程与进程和进程与线程
    在这里插入图片描述

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

  • 看一下传统的进程使用资源情况
    在这里插入图片描述

  • 现代操作系统的情况
    在这里插入图片描述
    在这里插入图片描述
    查看CPU的一些信息
    在这里插入图片描述

在这里插入图片描述

(二)线程实现

1、多线程实现分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1)Thread实现多线程

(1)概念部分

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

(2)启动多线程

  • 看一下错误的调用
    在这里插入图片描述
    在这里插入图片描述
  • 看一下正确情况
    在这里插入图片描述
    在这里插入图片描述
  • 分析原因
    在这里插入图片描述
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();
  • 异常分析
    在这里插入图片描述
    在这里插入图片描述
  • start0分析
    在这里插入图片描述
    在这里插入图片描述
  • 启动总结
    在这里插入图片描述

2)Runnable实现多线程

(1)看概念

在这里插入图片描述
package java.lang.Runnable
在这里插入图片描述
在这里插入图片描述

(2)实现多线程

  • 这样编写
    在这里插入图片描述

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

在这里插入图片描述
通过这里发现都是去调用了init方法,再去看init方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

在这里插入图片描述

3)Thread与Runnable之间的关系

(1)明白继承关系

public class Thread implements Runnable
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 这样启动都是一个接口
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    使用Thread类也同样可以实现数据的共享
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

(2)小总结

在这里插入图片描述

4)使用Callable实现多线程

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

(1) 传统Runnable存在的问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)看看callable接口

在这里插入图片描述
在这里插入图片描述

  • 来看看Future接口
    在这里插入图片描述
    在这里插入图片描述

(3)再来看继承关系

在这里插入图片描述

  • 再来看RunnableFuture的实现类
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 再来看继承关系
    在这里插入图片描述
    在这里插入图片描述

(4)Callable实现多线程

在这里插入图片描述
在这里插入图片描述

(三)多线程的操作

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

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

(1)看图分析

在这里插入图片描述

(2)过程分析

在这里插入图片描述
在这里插入图片描述

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)获取线程名称

在这里插入图片描述
在这里插入图片描述

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

在这里插入图片描述
在这里插入图片描述
强烈不建议这样进行修改操作
在这里插入图片描述

  • 当我们设置的名字的时候
    在这里插入图片描述

  • 当我们不进行手动设置名字的时候呢【为什么能自动编号呢】
    在这里插入图片描述
    原因其实就是如下
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 观察线程的获取
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

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

(4)线程休眠

  • 看一下方法
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 看一下异常继承关系
    在这里插入图片描述
    在这里插入图片描述

  • 线程休眠【如下处理就感觉线程A和B是一起执行的一样,这是为什么呢】
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

(5)线程中断

  • 看点概念
    在这里插入图片描述
    在这里插入图片描述
  • 它有如下的一些方法
    在这里插入图片描述

(5)线程的强制执行

在这里插入图片描述
正常情况下我们是多个线程在竞争去抢夺,但是有特殊情况下,某个线程会强制抢夺。
在这里插入图片描述

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)线程礼让

在这里插入图片描述

  • 像这样的话就感觉差不多是交替执行的【仅仅是感觉】
    在这里插入图片描述
  • 礼让情况
    在这里插入图片描述
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)线程优先级

在这里插入图片描述

  • 首先模拟三个线程执行
    在这里插入图片描述
  • 主方法(主线程)决定了子线程的优先级
    在这里插入图片描述
  • 优先是可以修改的,在线程启动之前。【你设置了也不起什么卵用】
    在这里插入图片描述
    在这里插入图片描述
    优先级高的,有可能先执行,仅仅是有可能。

(四)线程同步与死锁

1、同步问题

1)问题的引入

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

  • 创建5个线程进行卖票处理
    在这里插入图片描述
    并不是加入了延迟才会出现这个问题,仅仅是更加明显而已。
    在这里插入图片描述
    能让问题更加明显的原因是我们线程休眠正好处于了修改和检查的期间,所以更加明显。
    在这里插入图片描述
    当最后一张票被5个线程抢着了,同时对原来的数据进行减1,那就会出现了这个了。

2)线程同步处理

在这里插入图片描述
在这里插入图片描述

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

  • 可以采用synchronized(同步对象) {业务逻辑}
    在这里插入图片描述
    在这里插入图片描述
  • 也可以这样写
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)使用同步方法实现

在这里插入图片描述

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、线程死锁

在这里插入图片描述


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();
    }
}

在这里插入图片描述
在这里插入图片描述
只有用点工具进行监控,现实生活中很难预测。

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

3、生产者和消费者

1)生产者和消费者模型

(1)看概念

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)类结构分析

在这里插入图片描述
在这里插入图片描述

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();
    }
}

  • 观察结果
    在这里插入图片描述
    在这里插入图片描述
    这些问题并不是加上sleep才会出现问题的,仅仅是我们现在电脑比价牛逼,不加sleep很少出现问题。

(2)类结构分析

在这里插入图片描述

(3)解决数据同步问题

在这里插入图片描述

  • 问题分析
    在这里插入图片描述
  • 代码实现
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();
    }
}

  • 看结果分析:有重复生产和重复消费
    在这里插入图片描述

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

  • 问题分析和方法学习
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    显示肯定不用这种来处理,具体的可以学习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();
    }
}

  • 观察结果
    在这里插入图片描述

3)优雅的停止线程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 停止多线程
    在这里插入图片描述
    在这里插入图片描述

(五)线程相关其他知识

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();
    }
}

  • 案例分析
    在这里插入图片描述
    在这里插入图片描述

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();
    }
}

在这里插入图片描述

  • 那既然它实现不了同步,那这关键字有什么用呢?
    在这里插入图片描述
    在这里插入图片描述

  • 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、电脑生产面试题

在这里插入图片描述
在这里插入图片描述

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<String> {
    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<String> futureTask = new FutureTask<>(resource);
        FutureTask<String> futureTask1 = new FutureTask<>(resource);
        FutureTask<String> 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可以实现可重复锁,性能更高效。
    在这里插入图片描述

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

  • 来看一下Lock的莫办
    在这里插入图片描述
  • 看看代码
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();
        }
    }


}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
多线程lambda表达式是两个不同的概念,但它们可以结合使用来实现多线程编程。 在Java中,可以使用lambda表达式来简化多线程编程。Lambda表达式可以将一个函数作为参数传递给另一个函数或方法,并且可以在需要函数式接口的地方使用。 在多线程编程中,通常使用java.util.concurrent包中的ExecutorService来创建线程池并管理线程的执行。可以使用lambda表达式来定义要执行的任务。 下面是一个示例代码,展示了如何使用lambda表达式创建一个多线程任务: ``` import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class MultiThreadLambdaExample { public static void main(String[] args) { // 创建一个包含两个线程的线程池 ExecutorService executor = Executors.newFixedThreadPool(2); // 使用lambda表达式定义要执行的任务 Runnable task1 = () -> { System.out.println("Task 1 is running"); }; Runnable task2 = () -> { System.out.println("Task 2 is running"); }; // 提交任务给线程池执行 executor.submit(task1); executor.submit(task2); // 关闭线程池 executor.shutdown(); } } ``` 在上面的示例中,我们使用lambda表达式定义了两个任务(task1和task2),然后将它们提交给线程池执行。每个任务都会打印一条消息。 请注意,这只是一个简单的示例,实际的多线程应用可能涉及更加复杂的任务和线程管理。但是,lambda表达式可以帮助简化多线程编程,并提供更清晰和简洁的代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值