iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >怎么在Java中使用线程交替打印数字和字母
  • 842
分享到

怎么在Java中使用线程交替打印数字和字母

2023-06-14 09:06:23 842人浏览 泡泡鱼
摘要

今天就跟大家聊聊有关怎么在Java中使用线程交替打印数字和字母,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。 park 和 unparkpackage cn.bridgel

今天就跟大家聊聊有关怎么在Java中使用线程交替打印数字和字母,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

park 和 unpark

package cn.bridgeli.demo; import com.Google.common.collect.Lists; import java.util.List;import java.util.concurrent.locks.LockSupport; public class Thread_Communication_Park_Unpark {     static Thread t1 = null;    static Thread t2 = null;     public static void main(String[] args) {         final List<Integer> integers = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7);        final List<String> strings = Lists.newArrayList("A", "B", "C", "D", "E", "F", "G");         t1 = new Thread(() -> integers.forEach(item -> {            System.out.print(item);            LockSupport.unpark(t2);            LockSupport.park();        }), "t1");         t2 = new Thread(() -> strings.forEach(item -> {            LockSupport.park();            System.out.print(item);            LockSupport.unpark(t1);        }), "t2");         t1.start();        t2.start();    } }

这个是最简单的实现方法,LockSupport.park() 使当前线程阻塞,而 LockSupport.unpark() 则表示唤醒一个线程,所以他需要一个参数,表示你要唤醒哪个线程,很好理解,也比较简单。

2. synchronized、notify、wait

package cn.bridgeli.demo; import com.google.common.collect.Lists; import java.util.List; public class Thread_Communication_Notify_Wait {     public static void main(String[] args) {         final Object o = new Object();        final List<Integer> integers = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7);        final List<String> strings = Lists.newArrayList("A", "B", "C", "D", "E", "F", "G");         new Thread(() -> {            synchronized (o) {                integers.forEach(item -> {                    System.out.print(item);                    o.notify();                    try {                        o.wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                });                 o.notify();            }        }, "t1").start();         new Thread(() -> {            synchronized (o) {                strings.forEach(item -> {                    System.out.print(item);                    o.notify();                    try {                        o.wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                });                o.notify();            }        }, "t2").start();    }}

这是一个比较传统的写法,也是比较难理解的一个写法,掌握了这种写法之后,对 synchronized、notify、wait 的认识也会有一个新高度,下面就简单解析一下这种写法:

我们都知道 synchronized 是一把,而锁是什么?就是一个第三方的互斥的一个资源,所以 synchronized (o),就表示我们对 o 这个对象加锁,是通过修改 o 的对象头实现的,也就是两个线程谁成功修改了 o 的对象头,那么谁就拿到了这把锁,然后就可以执行里面的相关逻辑,而没有成功修改 o 的对象头的线程,就只有进入到对象 o 的一个等待队列,等待被系统调度执行(这是一个比较简单的不是很准确说法,详细过程,等我将来再写一个文章想聊锁升级的过程);然后就是 o.notify(),刚说过 synchronized (o) 一堆线程争抢锁,没有抢到锁的线程进入对象 o 的等待队列,所以 o.notify() 含义就是从对象 o 的等待队列中随机叫醒一个线程,然后执行;最后是 o.wait() 的含义,他的含义也很简单,就是当前线程放到对象 o 的等待队列中,让出 CPU。

通过这段描述,所以大家肯定也可以学习到经常遇到的三个问题是怎么回事:1. wait 是否占用 CPU 资源,因为进入了等待队列,所以是不会占用的;2. 既然 notify、wait 是让唤醒线程和让线程进入等待的,为什么不是 Thread 类的方法,反而是 Object 的方法,因为 notify、wait 是配合 synchronized 一起使用的,不一定用在多线程中,他们控制的是 synchronized 锁定的对象的等待队列,而 synchronized 锁定的对象,肯定是一个 Object,所以 notify、wait 比如是 Object 对象的方法;3. 关于 synchronized (o) 括号里面是一个对象实例、Class 对象、锁定代码块、静态变量等等区别,只要明白 synchronized 修改的是什么,这些区别就一目了然了,不再赘述。

最后要说明的一个问题是:循环外边的 o.notify() 必不可少,有些同学写的时候可能随手就忘记了,或者不知道为什么需要最后再 notify 一下,其实仔细想一想就可以明白了,假设最后执行的是输出字母的线程,那么他之前一定是被执行输出数字的线程唤醒的,而执行输出数字的这个线程唤醒执行输出字母的线程之后,自身就进入等待队列了,所以循环结束之后,如果最后执行输出字母的线程没有唤醒执行输出数字的线程的话,那么执行输出数字的线程会一直 wait 阻塞在那里,将等到天荒地来海枯石烂永远无法结束。

3. Condition

package cn.bridgeli.demo; import com.google.common.collect.Lists; import java.util.List;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock; public class Thread_Communication_Condition {     public static void main(String[] args) {         final List<Integer> integers = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7);        final List<String> strings = Lists.newArrayList("A", "B", "C", "D", "E", "F", "G");         Lock lock = new ReentrantLock();        Condition condition1 = lock.newCondition();        Condition condition2 = lock.newCondition();         new Thread(() -> {            lock.lock();            try {                integers.forEach(item -> {                    System.out.print(item);                    condition2.signal();                    try {                        condition1.await();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                });                 condition2.signal();            } finally {                lock.unlock();            }        }, "t1").start();         new Thread(() -> {            lock.lock();            try {                strings.forEach(item -> {                    System.out.print(item);                    condition1.signal();                    try {                        condition2.await();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                });                condition1.signal();            } finally {                lock.unlock();            }        }, "t2").start();     } }

看完上述内容,你们对怎么在Java中使用线程交替打印数字和字母有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程网精选频道,感谢大家的支持。

--结束END--

本文标题: 怎么在Java中使用线程交替打印数字和字母

本文链接: https://www.lsjlt.com/news/269583.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么在Java中使用线程交替打印数字和字母
    今天就跟大家聊聊有关怎么在Java中使用线程交替打印数字和字母,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。 park 和 unparkpackage cn.bridgel...
    99+
    2023-06-14
  • Java 用两个线程交替打印数字和字母
    目录1. park 和 unpark2. synchronized、notify、wait3. Condition前一段时间听马士兵老师讲课,讲到某公司的一个面试,两个线程,其中一个...
    99+
    2022-11-12
  • throw和throws关键字怎么在java中使用
    throw和throws关键字怎么在java中使用?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。在程序中自定义类,大体上分为以下几个步骤:创建自定义异常类在方法...
    99+
    2023-06-06
  • 怎么在Java中使用线程计算数组和
    怎么在Java中使用线程计算数组和?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。代码一:五个线程交替累加计算数组之和,这种方法其实不如单线程直接累加快,因为交替累加需要前一...
    99+
    2023-06-15
  • 怎么在shell脚本中使用字符串和数组
    这篇文章将为大家详细讲解有关怎么在shell脚本中使用字符串和数组,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。字符串可以使用单引号和双引号定义字符串变量但是单引号中不支持变量解析#!&nb...
    99+
    2023-06-09
  • java不同版本在多线程中怎么使用随机数生成器
    这篇文章主要讲解了“java不同版本在多线程中怎么使用随机数生成器”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java不同版本在多线程中怎么使用随机数生成器”吧!如何在多线程中使用随机数生...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作