为什么需要线程间通信

让线程之间合作,提高运行效率。

volatile和synchronized关键字

实现原理

这两个方式都是采用共享内存的方式进行通信,通过同步机制保证数据可见性和排他性。

特点

  • 本质是数据共享。
  • 不能特定地传给某个线程数据,需要程序员自己编写逻辑。数据在各个线程的更新顺序由操作系统决定。
  • 不能过多使用,这样会降低程序执行效率。

使用案例

// 用于控制线程当前的执行状态
private volatile boolean flag = false; // 开启一条线程
Thread t1 = new Thread(new Runnable(){
void run(){
// 开关
while(!flag){
Thread.sleep(1000);
}
// 执行线程任务
doSometing();
}
}).start(); // 开始执行
public void start(){
flag = true;
}

这里通过volatile修饰的标志位flag实现其他线程对t1的控制。

等待和通知机制

等待/通知是Java实现多个进程交替协作的机制。

实现方法

Java提供了API实现该机制。

使用注意

  • 上述所有方法都必须放在一个同步块中。
  • 上述方法都只能由所处同步块的锁对象调用。
  • 调用notify()方法之后,只是将线程从等待队列中转移到阻塞队列,当线程得到锁之后,才能用wait()方法之后,继续执行程序。

经典范式

该范式分为两个部分,分别针对等待方(消费者)和通知方(生产者)。

生产者通过notify唤醒消费者。消费者通过wait等待生产者生产完毕。

生产者:

private volatile boolean flag = false;

synchronized(objectA) {
flag = true;
objectA.notify();
}

消费者:

synchronized(objectA) {
while(!flag) {
objectA.wait();
} doSomething();
}

超时等待

为了避免等待方无止境地等待,可以通过超时等待,跳出等待。

public void get(long mills){
synchronized( list ){
// 不加超时功能
if ( mills <= 0 ) {
while( list.isEmpty() ){
list.wait();
}
} // 添加超时功能
else {
boolean isTimeout = false;
while(list.isEmpty() && isTimeout){
list.wait(mills);
isTimeout = true;
} // doSometing……
}
}
}

代码中利用list作为中间变量装载数据。

管道流

什么是管道流

用于线程间的数据传输。传输媒介为内存。

实现方式

管道输入输出主要包括四种具体实现:PipedOutputStream、PipedInputStream、PipedWriter、PipedReader。分别对应字节流和字符流。

// 创建输入流与输出流对象
PipedWriter out = new PipedWriter();
PipedReader in = new PipedReader(); // 连接输入输出流
out.connect(in); // 创建写线程
class WriteThread extends Thread{
private PipedWriter out; public WriteThread(PipedWriter out){
this.out = out;
} public void run(){
out.write("lippon");
}
} // 创建读线程
class ReaderThread extends Thread{
private PipedReader in; public ReaderThread(PipedReader in){
this.in = in;
} public void run(){
in.read();
}
}

Thread.join

作用

  1. 让多个并发的线程串行执行。
  2. 当A线程调用B.jion(),那么,A会等待B结束后,再从jion继续执行。
  3. 如果被等待的线程执行很长的时间,那么join会抛出InterruptedException。当调用B.interrupt()之后,jion函数就会抛出异常。

实现原理

  1. join的底层采用wait() 方法进行停止运行。
  2. 然后当被等待线程终止后,会调用线程的notifyAll() 方法释等待队列中的线程。

实现方式

public static void main(String[] args){

    // 开启一条线程
Thread t = new Thread(new Runnable(){
public void run(){
// doSometing
}
}).start(); // 调用join,等待t线程执行完毕
try{
t.join();
}catch(InterruptedException e){
// 中断处理……
}
}

最新文章

  1. a版本冲刺第七天
  2. 实现携程X分钟前有人预定功能
  3. ECMAScript 6(ES6)有什么新东西
  4. protobuf框架简介
  5. 跟着百度学PHP[4]-OOP面对对象编程-1-什么是面对对象编程
  6. ubuntu14 谷歌输入法
  7. StructureMap使用方法(转)
  8. memcached 介绍
  9. 笔记:PHP查询mysql数据后中文字符乱码
  10. HDU-4737 A Bit Fun 维护
  11. Fast Matrix Operations
  12. jQuery 元素移除empty() remove()与detach()的区别?
  13. JUnit4基础 使用JUnit4进行单元测试
  14. jquery 中 eq()遍历方法 和:eq()选择器的区别
  15. ECShop安装及错误修复
  16. androidstudio上传代码到git上
  17. 【转帖】Linux的历史----Linux内核剖析(一)
  18. 5.Java中的数组.md
  19. 细数用anaconda安装mayavi时出现的各种问题
  20. apache2.4和2.2 的一些区别

热门文章

  1. python之 《zip,lambda, map》
  2. LVM划分磁盘及扩容缩容
  3. mysql密码问题
  4. FL Studio乐理教程之添加和弦
  5. React Native两种加载图片的方式
  6. C语言讲义——错误处理
  7. MOS管基础知识
  8. 冲刺随笔——Day_Two
  9. fist-冲刺第二天随笔
  10. 【SDOI2013】JZOJ8月3日提高组T4 直径