一、通过synchronized关键字

public class test {public static void main(String[] args) {MyObject object=new MyObject();ThreadA threadA=new ThreadA(object);ThreadB threadB=new ThreadB(object);threadA.start();threadB.start();}}class MyObject{synchronized public void methodA(){//do something}synchronized public void methodB(){//do something}
}class ThreadA extends Thread{private MyObject object;public ThreadA(MyObject object){this.object=object;}@Overridepublic void run(){super.run();object.methodA();}
}class ThreadB extends Thread{private MyObject object;public ThreadB(MyObject object){this.object=object;}@Overridepublic void run(){super.run();object.methodB();}
}

二、wait和notify

import org.omg.Messaging.SYNC_WITH_TRANSPORT;import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;public class test {public static void main(String[] args) {try {Object lock=new Object();ThreadA a=new ThreadA(lock);a.start();Thread.sleep(1000);ThreadB b=new ThreadB(lock);b.start();}catch (InterruptedException e){e.printStackTrace();}}}class MyList{private static List<String> list=new ArrayList<>();public static void add(){list.add("test");}public static int size(){return list.size();}
}class ThreadA extends Thread{private Object lock;public ThreadA(Object lock){super();this.lock=lock;}@Overridepublic void run(){try{synchronized (lock){if(MyList.size()!=5){System.out.println("wait begin:"+System.currentTimeMillis());lock.wait();System.out.println("wait end:"+System.currentTimeMillis());}}}catch (InterruptedException e){e.printStackTrace();}}
}class ThreadB extends Thread{private Object lock;public ThreadB(Object lock){super();this.lock=lock;}@Overridepublic void run(){try{synchronized (lock){for(int i=0;i<10;i++){MyList.add();if(MyList.size()==5){lock.notifyAll();System.out.println("已经发出了通知");}System.out.println("添加了"+(i+1)+"个元素");Thread.sleep(1000);}}}catch (InterruptedException e){e.printStackTrace();}}
}

结果:

wait begin:1602418383158
添加了1个元素
添加了2个元素
添加了3个元素
添加了4个元素
已经发出了通知
添加了5个元素
添加了6个元素
添加了7个元素
添加了8个元素
添加了9个元素
添加了10个元素
wait end:1602418394166

线程A要等待某个条件满足时(list.size()==5),才执行操作。线程B则向list中添加元素,改变list 的size。

A,B之间如何通信的呢?也就是说,线程A如何知道 list.size() 已经为5了呢?

这里用到了Object类的 wait() 和 notify() 方法。

当条件未满足时(list.size() !=5),线程A调用wait() 放弃CPU,并进入阻塞状态。

当条件满足时,线程B调用 notify()通知 线程A,所谓通知线程A,就是唤醒线程A,并让它进入可运行状态。

这种方式的一个好处就是CPU的利用率提高了。

但是也有一些缺点:比如,线程B先执行,一下子添加了5个元素并调用了notify()发送了通知,而此时线程A还执行;当线程A执行并调用wait()时,那它永远就不可能被唤醒了。因为,线程B已经发了通知了,以后不再发通知了。这说明:通知过早,会打乱程序的执行逻辑。

三、while轮询

import org.omg.Messaging.SYNC_WITH_TRANSPORT;import java.lang.annotation.Native;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;public class test {public static void main(String[] args) {MyList list=new MyList();ThreadA a=new ThreadA(list);a.setName("A");a.start();ThreadB b=new ThreadB(list);b.setName("B");b.start();}}class MyList{private List<String> list=new ArrayList<>();public void add(){list.add("elements");}public int size(){return list.size();}
}class ThreadA extends Thread{private MyList list;public ThreadA(MyList list){super();this.list=list;}@Overridepublic void run(){try{for(int i=0;i<10;i++){list.add();System.out.println("添加了:"+(i+1)+"个元素");Thread.sleep(1000);}}catch (InterruptedException e){e.printStackTrace();}}
}class ThreadB extends Thread{private MyList list;public ThreadB(MyList list){super();this.list=list;}@Overridepublic void run(){try{while(true){if(list.size()==5){System.out.println("线程B准备退出");throw new InterruptedException();}}}catch (InterruptedException e){e.printStackTrace();}}
}

在这种方式下,线程A不断改变条件,线程B不断通过while语句检测这个条件(list.size()==5)是否成立,从而实现了线程间的通信。但是这种方式会浪费CPU资源。

同时这种方式还存在另外一个问题,这就是轮询条件的可见性问题:
线程都是先把变量读取到本地线程栈空间,然后再去修改的本地变量。因此,如果线程B每次都在取本地的条件变量,那么尽管另外一个线程已经改变了轮询的条件,它也察觉不到,这样会造成死循环。

25行对list加上volatile限制后,这时程序会正常退出,不会陷入死循环。

private volatile List<String> list=new ArrayList<>();

四、管道通信

利用java.io.PipedInputStream和java.io.PipedOutputStream进行通信。

生产者每5s提供5个产品,放入管道
消费者每0.5s从管道中取一件产品,并打印剩余产品数量,打印产品信息(以数字替代)

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;public class test{public static void main(String[] args) throws InterruptedException {PipedOutputStream pos=new PipedOutputStream();PipedInputStream pis=new PipedInputStream();try {pis.connect(pos);}catch (IOException e){e.printStackTrace();}new MyProducer(pos).start();new MyConsumer(pis).start();}}class MyProducer extends Thread{private PipedOutputStream outputStream;private int index=0;public MyProducer(PipedOutputStream outputStream){this.outputStream=outputStream;}@Overridepublic void run(){while(true){try{for(int i=0;i<5;i++){outputStream.write(index++);}}catch (IOException e){e.printStackTrace();}try {Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}}
}class MyConsumer extends Thread{private PipedInputStream inputStream;public MyConsumer(PipedInputStream inputStream){this.inputStream=inputStream;}@Overridepublic void run(){while (true){try {Thread.sleep(500);}catch (InterruptedException e){e.printStackTrace();}try {int count=inputStream.available();if(count>0){System.out.println("rest product cout"+count);System.out.println("get product"+inputStream.read());}}catch (IOException e1){e1.printStackTrace();}}}
}

https://blog.csdn.net/Hadwin1991/article/details/73527835

Java线程间通信方式相关推荐

  1. java 线程间通信方式_「转」JAVA多线程之线程间的通信方式

    1. 同步 这里讲的同步是指多个线程通过synchronized关键字这种方式来实现线程间的通信. public class MyObject { synchronized public void m ...

  2. linux的进程与线程通信方式,Linux的进程/线程间通信方式总结

    Linux系统中的进程间通信方式主要以下几种: 同一主机上的进程通信方式 * UNIX进程间通信方式: 包括管道(PIPE), 有名管道(FIFO), 和信号(Signal) * System V进程 ...

  3. android线程间通信的几种方法_Android进程间和线程间通信方式

    进程:是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程:是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位 ...

  4. Android 进程间通信方式和线程间通信方式

    1.进程和线程 进程:是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程:是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独 ...

  5. 面试题:进程间通信方式,线程间通信方式

    一.进程间通信(IPC,Inter-Process Communication)是指在不同进程间传播或交换信息 1. 无名管道 特点 半双工(数据流向仅有一个方向),具有固定的读端和写端 只能用于父进 ...

  6. Linux的进程/线程间通信方式总结

    Linux系统中的进程间通信方式主要以下几种: 同一主机上的进程通信方式 * UNIX进程间通信方式: 包括管道(PIPE), 有名管道(FIFO), 和信号(Signal) * System V进程 ...

  7. Java线程间通信-回调的实现方式

    2019独角兽企业重金招聘Python工程师标准>>> Java线程间通信-回调的实现方式 Java线程间通信是非常复杂的问题的.线程间通信问题本质上是如何将与线程相关的变量或者对象 ...

  8. java线程间ThreadLocal的传递

    文章目录 1 场景 2 需确认问题 2.1 继承线程的ThreadLocal的含义 2.2 子线程内的ThreadLocal的值和父线程内的有什么关系? 2.3 父线程内的ThreadLocal清除后 ...

  9. Linux 线程间通信方式+进程通信方式

    1. linux下进程间通信的几种主要手段简介: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能 ...

  10. java线程间通信的方式

    java线程间通信的方式 1. 共享变量 2. 等待/通知 3. 管道流 1. 共享变量 volatile修饰的变量,线程间可见,可使用这种变量作为线程间传递消息的媒介: 延伸出来的,还有redis中 ...

最新文章

  1. SQLServer错误:过程 sp_addextendedproperty,第 xxx 行对象无效。'dbo.xxx.xxx' 不允许有扩展属性,或对象不存在。...
  2. profile matlab,使用profile功能对Matlab性能调优
  3. Golang并发——并发技术Goroutine和channel的使用、定时器、生产者消费者、条件变量、select
  4. NGUI_2.6.3_系列教程三
  5. 贝塔斯曼龙宇:李斌能征善战 提前七年兑现了自己的承诺
  6. 旧的非flash版Metalink的入口
  7. C中遇到错误error: jump to label [-fpermissive]的解决办法
  8. Atitit j2ee5 jee5 j2ee6 j2ee7 jee6 jee7 新特性
  9. 计算机上策略禁止用户安装,Win7系统组策略禁止安装软件、软件安装控制策略禁止方法...
  10. 加油,我看好你 本题由擂主Wfox提供 -flag{bc57380e-9f8d-4b1e-8432-794b54b5625f}
  11. ubuntu20.04 磁盘管理
  12. Windows 小技巧10--Windows常见软件、系统配置
  13. Matlab —— 02 基本操作与矩阵输入
  14. 机房环境监控系统的作用,环境与设备监控系统的作用
  15. docker-compose.yml修改volumes后重启不生效
  16. 一男老师每日百词转载+连载(2)
  17. 电商互动消息如何进行架构演进?
  18. sci期刊发表文章注意事项
  19. 数据库课程设计:图书借阅系统(Java+MySQL)
  20. 全国程序员薪酬大曝光!看完我酸了····

热门文章

  1. Flutter之SafeArea
  2. OkHttp之ConnectInterceptor简单分析
  3. 清明,我怀念那个回不去的故乡了
  4. centos7部署两个mysql_基于Canal和Kafka实现MySQL的Binlog近实时同步
  5. python语言适用于哪些领域_Python用于哪些领域
  6. 记一次网络访问故障排查
  7. JQuery自动点击事件加载load事件和 AJAX异步请求加载
  8. 线程结束后会自动关闭_多线程学习之如何中断线程
  9. dmg镜像如何写入u盘_最全macOS官方全家桶原版系统镜像
  10. python只保留大写字母_python - 匹配某一行并保留大写字母?