java多线程编程学习(线程间通信)
作者:JMCui 发布时间:2023-04-02 05:25:34
一、概要
线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就是成为整体的必用方案之一。可以说,使线程进行通信后,系统之间的交互性会更强大,在大大提高cpu利用率的同时还会使程序员对各线程任务在处理过程中进行有效的把控和监督。
二、等待/通知机制
1、"wait/notify"机制:等待/通知机制,wait使线程暂停运行,而notify 使暂停的线程继续运行。用一个厨师和服务员的交互来说明:
(1) 服务员取到菜的时间取决于厨师,所以服务员就有“等待”(wait)的状态。
(2) 厨师将菜放在“菜品传递台”上,其实就相当于一种通知(notify),这时服务员才可以拿到菜并交给就餐者。
2、wait()
(1) 使当前执行代码的线程进行等待。wait()方法是Object类的方法,该方法用来将当前线程置入“预执行队列”中,并且在wait()所在的代码行处停止执行,直到接收通知或被中断为止。
(2) 在调用wait()方法之前,线程必须获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait()方法,否则抛出IllegalMonitorStateException异常。(属于Runtime的一个子类,不需要try-catch 语句进行捕捉异常)
(3) 在调用wait()方法之后,当前线程释放锁,而此对象会进入线程等待池中,等待被唤醒。在从wait()返回前,线程与其他呈wait线程竞争重新获得锁。
(4) wait()方法可以被interrupt 打断并抛出InterruptedException。
(5) wait(long):带一个参数的wait(long)方法的功能是等待某一时间内是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒。
3、notify()
(1) 用来通知那些可能等待该对象的对象锁的其他线程。如果有多个线程等待,则由线程规划器随机挑选出其中一个呈wait状态的线程,对其发出通知notify,并使它等待获取该对象的对象锁。(注意!这里说的是等待,即在执行完notify()方法后,当前线程不会马上释放该对象锁,即wait()状态的线程也不会马上获得对象锁,需要将synchronized 代码块中的代码执行完后才释放锁!)
(2)也要在同步方法或同步块中调用,即在调用前,线程也必须获得该对象的对象级别锁,否则也会抛出IllegalMonitorStateException.
(3)当notify()发出通知,却没有wait()线程在等待时,则不作作用。
4、notifyAll()
(1) 可以使所有正在等待队列中的 等待同一共享资源(即同一个锁) 的"全部"线程从等待状态退出,进入可运行状态。
5、
6、假死:“假死”现象其实就是线程进入WAITING等待状态。如果全部线程都进入WAITING状态,则程序就不再执行任何功能了,整个项目呈停止状态。 出现这样的原因是因为:比如多个生产者和多个消费者的问题,“生产者”可能唤醒“生产者”,“消费者”可能唤醒“消费者”,唤醒了同类,导致线程不断在等待。怎么解决这个问题呢?将notify() 改成 notifyAll()方法即可,也就是将异类一同唤醒就可以了。
7、 Jave中 管道流(pipeStream)是一种特殊的流,可用于在不同的线程中直接传送数据。一个线程发送数据到输出管道,另一个线程从输入管道中读数据。通过使用管道,实现不同线程间的通信,而无须借助于类似临时文件之类的东西。JDK中提供了四个类来使线程间可以通信,其中包括字节流(PipedOutputStream、PipedInputStream)和字符流(PipedWriter、PipedReader)。
public class Run {
public static void main(String[] args) {
try {
WriteData writeData = new WriteData();
ReadData readData = new ReadData();
PipedOutputStream outputStream = new PipedOutputStream();
PipedInputStream inputStream = new PipedInputStream();
outputStream.connect(inputStream);//使两个Stream之间产生通信链接,这样才可以将数据进行输入输出
ThreadRead threadRead = new ThreadRead(readData, inputStream);
threadRead.start();
Thread.sleep(1000);
ThreadWrite threadWrite = new ThreadWrite(writeData, outputStream);
threadWrite.start();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
三、方法join的使用
1、在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时计算,主线程往往将早于子线程结束之前结束。这时,如果主线程想等待子线程执行完成之后再结束,比如子线程处理一个数据,主线程要取得这个数据中的值,就要用到join()方法了。
2、join()的作用是等待线程销毁,而使 当前线程进行无限期的阻塞,等待join()的线程销毁后再继续执行当前线程的代码。
3、同样的,join()方法可以被interrupt()方法打断并抛出InterruptedException异常。
4、join 与 synchronized 的区别?
(1) join()在内部使用wait() 方法进行等待。
(2) synchronized 关键字使用的是“对象监视器”原理作为同步。
5、方法join(long) 和 sleep(long)的区别?
(1) join(long)内部采用wait(long)方法实现,当执行wait(long)方法后,当前线程的锁被释放,那么其他线程也可以调用此线程中的同步方法了。即 join(long)之后,该线程释放锁,又需要和其他线程去争抢锁的资源。
(2) Thread.sleep(long)方法不释放锁。
四、类 ThreadLocal 的使用
1、变量值的共享可以使用public static 变量的形式,所有的线程都使用同一个public static 变量。如果想实现每一个线程都有自己的共享变量该如何解决呢?类ThreadLocal解决的就是每个线程绑定自己的值,可以将ThreadLocal类比喻成全局存放数据的盒子,盒子中可以存放每个线程的私有数据。
2、类ThreadLocal 具有隔离性,即每个线程都可以存入自己线程的数据而互不影响,而取到的也是自己线程存入的数据。
五、类InheritableThreadLocal的使用
1、InheritableThreadLocal类继承于ThreadLocal类,所以它具有ThreadLocal类的特性,但又是一种特殊的ThreadLocal,其特殊性在于InheritableThreadLocal变量值会自动传递给所有子线程,而普通ThreadLocal变量不行;而且,通过重写这个类中的 childValue 方法,子线程的值可以作为父线程值的一个任意函数。
备注:
(1) 什么是子线程?
包含在 Thread thread = new Thread(new ThreadStart(delegate{
}));里面均视为子线程。(个人理解)
(2) 什么是主线程?
UI界面和Main函数均为主线程,除了“不包含在Thread里面的程序”均可 视为主线程。(个人理解)
来源:http://www.cnblogs.com/jmcui/p/7503296.html


猜你喜欢
- Flutter 是 Google 开源的 UI 工具包,帮助开发者通过一套代码库高效构建多平台精美应用,支持移动、Web、桌面和嵌入式平台。
- 前言之前我们探讨过一个.class文件是如何被加载到jvm中的。但是jvm内又是如何划分内存的呢?这个内被加载到了那一块内存中?jvm内存划
- 如下所示: /** * 判断某个界面是否在前台 * * @param context
- 1. JVM 运行时数据区JVM运行时数据区可以分为元空间,堆,虚拟机栈,本地方法栈,程序计数器五大块。元空间(方法区):存放类模版对象,是
- Android 实现代码混淆的实例1、简介代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,
- 【漏洞通告】2月19日,NVD发布安全通告披露了jackson-databind由JNDI注入导致的远程代码执行漏洞(CVE-2020-88
- 国际化(internationalization)是设计和制造容易适应不同区域要求的产品的一种方式。它要求从产品中抽离所有地域语言,国家/地
- 一、下载Unity首先去官网下载对应版本的 UnityHubUnity官网地址: https://unity.cn/releases&nbs
- Java 理解 ThreadLocal摘要: ThreadLocal 又名线程局部变量,是 Java 中一种较为特殊的线程绑定机制,用于保证
- 引言最近一个朋友正在找工作,他说在笔试题中遇到Equals和==有什么区别的题,当时跟他说如果是值类型的,它们没有区别,如果是引用类型的有区
- 本文实例讲述了Java枚举类用法。分享给大家供大家参考。具体如下:package com.school.stereotype; /** *
- 理论上Object类是所有类的父类,即直接或间接的继承java.lang.Object类。由于所有的类都继承在Object类,因此省略了ex
- 本文实例为大家分享了Android ViewPager实现轮播图效果的具体代码,供大家参考,具体内容如下先上一张效果图:说到ViewPage
- protected 来谈谈protected访问权限问题。看下面示例1:Test.javaclass MyObject {}public c
- SpringBoot接收文件和对象使用场景:某个接口,需要同时接收文件和实体,也就是参数一、这个时候,前端就不能json格式传送数据了,要用
- 问题注意:本人使用的Spring Boot 2.0.2, 对1.5.x系列未必有用。官方文档在这里直接解决办法0, 移除spring-boo
- 开发Android应用中,随着功能越来越多,启动速度越来越慢。有没有办法让自己应用启动速度快一点呢?方法是人想出来的。先说说我的实现方法:1
- 内部类基本介绍一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer
- 一、创建数据库 1、新建数据库帮助类 包名——右击—&am
- 这是一个及其常见的问题,网上已经有关于这个问题的很多讨论。但是我觉得都是不求甚解,有一些还是在误导别人。下面我来说下我对这三者的理解,如有错