Java Thread多线程开发中Object类怎么使用

这篇“Java Thread多线程开发中Object类怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java Thread多线程开发中Object类怎么使用”文章吧。

    方法概览

    Thread

    Java Thread多线程开发中Object类怎么使用

    wait  notify notifyAll方法详解

    作用

    阻塞阶段

    使用了wait方法之后,线程就会进入阻塞阶段,只有发生以下四种情况中的其中一个,线程才会被唤醒

    • 另一个线程调用了这个线程的notify方法,刚好唤醒的是本线程

    • 另一个线程调用了这个对象的notifyAll方法

    • 过了wait规定的超时时间

    • 线程调用了interrupt

    唤醒阶段

    notify会唤醒单个处于阻塞状态的线程,唤醒的线程是随机的

    notify和wait都需要写在synchronized代码块里,不然会抛出异常

    notifyAll会唤醒所有等待的线程

    遇到中断

    执行wait方法之后,被中断,会抛出InterruptedException这个异常

    代码展示

    • 展示wait和notify的基本用法

    • 该代码执行wait方法之后会释放锁,然后thread2执行notify方法

    • notify方法执行完毕之后,并没有立即释放锁,而是接着执行之后的代码,也就是打印“Thread2调用notify”这句话

    • thread2执行完毕之后,会进行释放锁,thread1才会继续执行

    • 在此期间,thread1虽然被唤醒,但是一直在等待thread2同步代码块里面的代码执行完毕

    public class Wait {
        public static void main(String[] args) throws InterruptedException {
            Thread1 thread1 = new Thread1();
            Thread2 thread2 = new Thread2();
            thread1.start();
            Thread.sleep(200);
            thread2.start();
        }
        public static Object object = new Object();
        static class Thread1 extends Thread {
            @Override
            public void run() {
                synchronized (object) {
                    System.out.println("Thread1执行");
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread1获取锁");
                }
            }
        }
        static class Thread2 extends Thread {
            @Override
            public void run() {
                synchronized (object) {
                    object.notify();
                    System.out.println("Thread2调用notify");
                }
            }
        }
    }
    /*
    Thread1执行
    Thread2调用notify
    Thread1获取锁
    * */
    • notify和notifyAll的展示

    • 第一个输出:threadc调用notifyAll

    • 第二个输出:threadc调用notify

    • 调用notify的时候,程序并没有结束,threadb陷入等待

    public class notifyOrAll implements Runnable{
        private static final Object a = new Object();
        public static void main(String[] args) throws InterruptedException {
            Runnable r = new notifyOrAll();
            Thread threada = new Thread(r);
            Thread threadb = new Thread(r);
            Thread threadc = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (a) {
    //                    a.notifyAll();
                        a.notify();
                        System.out.println(Thread.currentThread().getName() + "notify");
                    }
                }
            });
            threada.start();
            Thread.sleep(200);
            threadb.start();
            Thread.sleep(200);
            threadc.start();
        }
        @Override
        public void run() {
            synchronized (a) {
                System.out.println(Thread.currentThread().getName() + "得到锁");
                try {
                    System.out.println(Thread.currentThread().getName() + "wait");
                    a.wait();
                    System.out.println(Thread.currentThread().getName() + "wait结束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /*
    Thread-0得到锁
    Thread-0wait
    Thread-1得到锁
    Thread-1wait
    Thread-2notifyAll
    Thread-1wait结束
    Thread-0wait结束
    * */
    /*
    Thread-0得到锁
    Thread-0wait
    Thread-1得到锁
    Thread-1wait
    Thread-2notify
    Thread-0wait结束
    * */
    • 只释放当前monitor

    • 证明wait只释放当前的那把锁

    public class OwnMonitor {
        private static volatile Object a = new Object();
        private static volatile Object b = new Object();
        public static void main(String[] args) throws InterruptedException {
            Thread threadA = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (a) {
                        System.out.println("threadA得到a");
                        synchronized (b) {
                            System.out.println("threadA得到锁b");
    
                            try {
                                System.out.println("threadA释放a");
                                a.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            });
            Thread threadB = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (a) {
                        System.out.println("threadB得到a");
                        System.out.println("threadB要获取b");
                        synchronized (b) {
                            System.out.println("threadB得到b");
                        }
                    }
                }
            });
            threadA.start();
            Thread.sleep(1000);
            threadB.start();
        }
    }
    /*
    threadA得到a
    threadA得到锁b
    threadA释放a
    threadB得到a
    threadB要获取b
    * */

    特点

    • 执行这些方法必须先获取锁

    • notify只能换取一个,而且是随机的

    • 都属于Object。任何对象都可以调用

    • 都是native final修饰的

    当线程从wait状态刚被唤醒时,通常不能直接得到锁,那就会从waiting状态转换到blocked状态,抢到锁之后状态转变为runnable

    如果发生异常,则直接跳到Terminated状态

    通过wait notify方法实现生产者和消费者

    • 将storge当作生产者和消费者进行工作的仓库

    • 如果storge中没有数据,生产者就开始wait

    • 如果storge中数据满了,消费者就开始wait

    • 生产者和消费者每进行一次生产和消费,就执行notify

    public class ProducerConsumer {
        public static void main(String[] args) {
            Storge storge = new Storge();
            Producer producer = new Producer(storge);
            Consumer consumer = new Consumer(storge);
            new Thread(producer).start();
            new Thread(consumer).start();
        }
    }
    class Producer implements Runnable {
        private Storge storge;
        public Producer(Storge storge) {
            this.storge = storge;
        }
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                storge.put();
            }
        }
    }
    class Consumer implements Runnable {
        private Storge storge;
        public Consumer(Storge storge) {
            this.storge = storge;
        }
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                storge.take();
            }
        }
    }
    class Storge {
        private int maxSize;
        private LinkedList<Date> storge;
        public Storge() {
            maxSize = 10;
            storge = new LinkedList<>();
        }
        public synchronized void put() {
            while (storge.size() == maxSize) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            storge.add(new Date());
            System.out.println("已经有了" + storge.size());
            notify();
        }
        public synchronized void take() {
            while (storge.size() == 0) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("拿到了" + storge.poll() + "还剩" + storge.size());
            notify();
        }
    }

    sleep方法详解

    作用:让线程在预期的时间执行,其他时间不占用CPU资源

    特点:和wait不一样,sleep不释放锁

    sleep不会释放锁

    证明sleep不会释放 synchronized锁

    public class SleepSyn implements Runnable{
        public static void main(String[] args) {
            SleepSyn sleepSyn = new SleepSyn();
            new Thread(sleepSyn).start();
            new Thread(sleepSyn).start();
        }
        @Override
        public void run() {
            syn();
        }
        private synchronized void syn() {
            System.out.println(Thread.currentThread().getName() + "获取锁");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "释放锁");
        }
    }
    /*
    * Thread-0获取锁
    Thread-0释放锁
    Thread-1获取锁
    Thread-1释放锁
    * */

    证明sleep不释放Lock锁

    public class sleepLock implements Runnable{
        private static final Lock LOCK = new ReentrantLock();
        @Override
        public void run() {
            LOCK.lock();
            System.out.println(Thread.currentThread().getName() + "获取锁");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                LOCK.unlock();
            }
            System.out.println(Thread.currentThread().getName() + "释放锁");
        }
        public static void main(String[] args) {
            sleepLock sleepLock = new sleepLock();
            new Thread(sleepLock).start();
            new Thread(sleepLock).start();
        }
    }
    /*
    * Thread-0获取锁
    Thread-0释放锁
    Thread-1获取锁
    Thread-1释放锁
    * */

    sleep响应中断

    • 抛出InterruptedException

    • 会清除中断状态

    • 中断之后,抛出异常继续执行

    public class sleepInterrupted implements Runnable{
        public static void main(String[] args) throws InterruptedException {
            Thread thread = new Thread(new sleepInterrupted());
            thread.start();
            Thread.sleep(2000);
            thread.interrupt();
        }
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(new Date());
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    System.out.println("中断");
                    e.printStackTrace();
                }
            }
        }
    }
    /*
    * Fri Jan 27 21:11:57 CST 2023
    Fri Jan 27 21:11:58 CST 2023
    中断
    Fri Jan 27 21:11:59 CST 2023
    java.lang.InterruptedException: sleep interrupted
       at java.lang.Thread.sleep(Native Method)
       at java.lang.Thread.sleep(Thread.java:340)
       at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
       at com.jx.JavaTest.ThreadObjectMethod.sleepInterrupted.run(sleepInterrupted.java:21)
       at java.lang.Thread.run(Thread.java:748)
    Fri Jan 27 21:12:00 CST 2023
    Fri Jan 27 21:12:01 CST 2023
    Fri Jan 27 21:12:02 CST 2023
    Fri Jan 27 21:12:03 CST 2023
    Fri Jan 27 21:12:04 CST 2023
    Fri Jan 27 21:12:05 CST 2023
    Fri Jan 27 21:12:06 CST 2023
    Process finished with exit code 0
    * */

    总结

    sleep方法可以让线程进入waiting状态,不占用CPU资源,但是不释放锁,规定时间之后再运行

    休眠期间如果被打断,会抛出异常并清除中断状态

    join方法详解

    新线程加入,主线程等子线程执行完毕

    代码展示

    • 前一个结果是使用join

    • 后一个结果是没使用join

    • 可知使用join之后,主线程会等join的线程执行完毕再继续执行

    public class join {
        public static void main(String[] args) throws InterruptedException {
            Thread thread1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "执行完毕");
                }
            });
            Thread thread2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "执行完毕");
                }
            });
            thread1.start();
            thread2.start();
            System.out.println("开始等待子线程运行");
    //        thread1.join();
    //        thread2.join();
            System.out.println("所有线程执行完毕");
        }
    }
    /*
    * 开始等待子线程运行
    Thread-0执行完毕
    Thread-1执行完毕
    所有线程执行完毕
    * */
    /*
    * 开始等待子线程运行
    所有线程执行完毕
    Thread-1执行完毕
    Thread-0执行完毕
    * */
    • 遇到中断

    • 第一个的运行结果是主线程没中断的打印结果

    • 第二个的运行结果是join期间进行中断的打印结果,可知在打印了“子线程运行完毕”之后,依然打印了“启动”两个字,可知会造成运行混乱

    • 可以在捕获异常的代码块中,将join的线程也中断,可以解决上面的问题

    public class joinInterrupt {
        public static void main(String[] args) {
            Thread main1 = Thread.currentThread();
            Thread thread1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        main1.interrupt();
                        Thread.sleep(2000);
                        System.out.println("启动");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            thread1.start();
            System.out.println("join");
            try {
                thread1.join();
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() + "中断");
                // thread1.interrupt();
                e.printStackTrace();
            }
            System.out.println("子线程运行完毕");
        }
    }
    /*
    * join
    启动
    子线程运行完毕
    * */
    /*
    * join
    main中断
    子线程运行完毕
    java.lang.InterruptedException
       at java.lang.Object.wait(Native Method)
       at java.lang.Thread.join(Thread.java:1252)
       at java.lang.Thread.join(Thread.java:1326)
       at com.jx.JavaTest.ThreadObjectMethod.joinInterrupt.main(joinInterrupt.java:23)
    启动
    Process finished with exit code 0
    * */
    /*
    * join
    main中断
    子线程运行完毕
    java.lang.InterruptedException: sleep interrupted
       at java.lang.Thread.sleep(Native Method)
       at com.jx.JavaTest.ThreadObjectMethod.joinInterrupt$1.run(joinInterrupt.java:13)
       at java.lang.Thread.run(Thread.java:748)
    java.lang.InterruptedException
       at java.lang.Object.wait(Native Method)
       at java.lang.Thread.join(Thread.java:1252)
       at java.lang.Thread.join(Thread.java:1326)
       at com.jx.JavaTest.ThreadObjectMethod.joinInterrupt.main(joinInterrupt.java:23)
    Process finished with exit code 0
    * */

    join期间,线程处于WAITING状态

    public class joinStates {
        public static void main(String[] args) throws InterruptedException {
            Thread main1 = Thread.currentThread();
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(3000);
                        System.out.println(main1.getState());
                        System.out.println("子线程运行结束");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            thread.start();
            System.out.println("join");
            thread.join();
            System.out.println("运行完毕");
        }
    }
    /*
    * join
    WAITING
    子线程运行结束
    运行完毕
    * */

    yield方法

    用来释放CPU时间片,但是不一定能达到预期的效果,因为有时CPU资源不紧张,无需yield

    和sleep的区别是:sleep期间不会被再次调度但是yield会立刻处于竞争状态,还会随时再次被调度

    以上就是关于“Java Thread多线程开发中Object类怎么使用”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程之家行业资讯频道。

    版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

    相关推荐


    本文从从Bitcask存储模型讲起,谈轻量级KV系统设计与实现。从来没有最好的K-V系统,只有最适合应用业务实际场景的系统,做任何的方案选择,要结合业务当前的实际情况综合权衡,有所取有所舍。
    内部的放到gitlab pages的博客,需要统计PV,不蒜子不能准确统计,原因在于gitlab的host设置了strict-origin-when-cross-origin, 导致不蒜子不能正确获取referer,从而PV只能统计到网站的PV。 为了方便统计页面的PV,这里简单的写了一个java程
    PCM 自然界中的声音非常复杂,波形极其复杂,通常我们采用的是脉冲代码调制编码,即PCM编码。PCM通过抽样、量化、编码三个步骤将连续变化的模拟信号转换为数字编码。 采样率 采样频率,也称为采样速度或者采样率,定义了每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示。采样频率的倒数
    本文介绍如何离线生成sst并在线加载,提供一种用rocksdb建立分布式kv系统替换mongodb的思路
    验证用户输入是否正确是我们应用程序中的常见功能。Spring提供了`@Valid`和@`Validated`两个注解来实现验证功能,本文详细介绍 [@Valid]和[@Validated]注解的区别 。
    引入pdf2dom &lt;dependency&gt; &lt;groupId&gt;net.sf.cssbox&lt;/groupId&gt; &lt;artifactId&gt;pdf2dom&lt;/artifactId&gt; &lt;version&gt;1.8&lt;/version&
    grafana 是一款非常优秀的可视化报表工具,有设计精良的可视化工具,今天来聊一聊如何将grafana集成到自己的应用中。 原理是: grafana允许iframe访问,开启auth.proxy, java 后端鉴权后代理grafana 前端通过iframe访问后端代理过的grafana graf
    介绍 Call Graph是一款IDEA插件,用于可视化基于IntelliJ平台的IDE的函数调用图。 这个插件的目标是让代码更容易理解,有助于读懂和调试代码。当前只支持Java。针对Typescript、Javascript或Python工具,可以使用作者的另外一款工具Codemap(https:
    原理 通过线程安全findAndModify 实现锁 实现 定义锁存储对象: /** * mongodb 分布式锁 */ @Data @NoArgsConstructor @AllArgsConstructor @Document(collection = &quot;distributed-loc
    Singleton 单例模式 单例模式是确保每个应用程序只存在一个实例的机制。默认情况下,Spring将所有bean创建为单例。 你用@Autowired获取的bean,全局唯一。 @RestController public class LibraryController { @Autowired
    pipeline 分布式任务调度器 目标: 基于docker的布式任务调度器, 比quartzs,xxl-job 更强大的分布式任务调度器。 可以将要执行的任务打包为docker镜像,或者选择已有镜像,自定义脚本程序,通过pipeline框架来实现调度。 开源地址: https://github.c
    python训练的模型,转换为onnx模型后,用python代码可以方便进行推理,但是java代码如何实现呢? 首先ONNX 推理,可以使用`onnxruntime` ```xml com.microsoft.onnxruntime onnxruntime 1.15.1 ``` 另外,训练的模型需要
    要获取内网地址,可以尝试连接到10.255.255.255:1。如果连接成功,获取本地套接字的地址信息就是当前的内网IP。 python实现: ```python import socket def extract_ip(): st = socket.socket(socket.AF_INET, s
    为什么要有索引 gremlin 其实是一个逐级过滤的运行机制,比如下面的一个简单的gremlin查询语句: g.V().hasLabel(&quot;label&quot;).has(&quot;prop&quot;,&quot;value&quot;) 运行原理就是: 找出所有的顶点V 然后过滤出
    最近在分析一个应用中的某个接口的耗时情况时,发现一个看起来极其普通的对象创建操作,竟然每次需要消耗 8ms 左右时间,分析后发现这个对象可以通过对象池模式进行优化,优化后此步耗时仅有 0.01ms。
    点赞再看,动力无限。Hello world : ) 微信搜「 程序猿阿朗 」。 本文 Github.com/niumoo/JavaNotes 和 未读代码网站 已经收录,有很多知识点和系列文章。 此篇文章介绍 Java JMX 技术的相关概念和具体的使用方式。 当前文章属于Java 性能分析优化系列
    如何将Java JAR 转化为 win/mac/linux 独立可执行程序?不需要预装 JRE 运行?
    点赞再看,动力无限。 微信搜「 程序猿阿朗 」。 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章。 Java 19 在2022 年 9 月 20 日正式发布,Java 19 不是一个长期支持版本,直到 2023 年 3 月它将被 JD
    点赞再看,动力无限。Hello world : ) 微信搜「 程序猿阿朗 」。 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章。 前言 Java 反编译,一听可能觉得高深莫测,其实反编译并不是什么特别高级的操作,Java 对于 Cla
    JSON 对于开发者并不陌生,如今的 WEB 服务、移动应用、甚至物联网大多都是以 **JSON** 作为数据交换的格式。学习 JSON 格式的操作工具对开发者来说是必不可少的。这篇文章将介绍如何使用 **Jackson** 开源工具库对 JSON 进行常见操作。