美文网首页
线程间的通信

线程间的通信

作者: JBryan | 来源:发表于2020-01-31 20:55 被阅读0次
1.wait、notify、notifyAll

何时使用
在多线程环境下,有时候一个线程的执行,依赖于另外一个线程的某种状态的改变,这个时候,我们就可以使用wait与notify或者notifyAll。
wait跟sleep的区别
wait会释放持有的锁,而sleep不会,sleep只是让线程在指定的时间内,不去抢占cpu的资源。
注意点
wait notify必须放在同步代码块中, 且必须拥有当前对象的锁。即不能取得A对象的锁,而调用B对象的wait。哪个对象wait,就得调哪个对象的notify。
notify跟notifyAll的区别
nofity随机唤醒一个等待的线程​,notifyAll唤醒所有在该对象上等待的线程

2.使用管道流进行通信

以内存为媒介,用于线程之间的数据传输。
主要有面向字节:【PipedOutputStream、PipedInputStream】、面向字符【PipedReader、PipedWriter】
Reader用于读取内存中的数据

package com.ljessie.sinopsis.communication.pipe;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.util.stream.Collectors;

public class Reader implements Runnable{

    private PipedInputStream pis;
    
    public Reader(PipedInputStream pis) {
        this.pis = pis;
    }
    
    @Override
    public void run() {
        if(pis != null) {
            String collect = new BufferedReader(new InputStreamReader(pis)).lines().collect(Collectors.joining("\n"));
            System.out.println(collect);
        }
        try {
            pis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }   
    }
}

Main获取控制台输入的数据,写到内存中。

package com.ljessie.sinopsis.communication.pipe;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class Main {
    
    public static void main(String[] args) throws IOException {
        PipedInputStream pis = new PipedInputStream();
        PipedOutputStream pos = new PipedOutputStream();
        
        pos.connect(pis);
        
        new Thread(new Reader(pis)).start();
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            pos.write(bufferedReader.readLine().getBytes());
        } finally {
            bufferedReader.close();
            pos.close();
        }
    }
}
3.Thread.join通信

使用场景:线程A执行到一半,需要一个数据,这个数据需要线程B去执行修改,只有B修改完成之后,A才能继续操作。

package com.ljessie.sinopsis.communication.join;

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"开始运行");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"运行结束");
            }
        };
        new Thread() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"开始运行");
                thread.start();
                try {
                    thread.join();
                } catch (InterruptedException e) {
                        e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"运行结束");
            }
        }.start();
    }
}
4.ThreadLocal使用

线程变量,是一个以ThreadLocal对象为键、任意对象为值的存储结构。为每个线程单独存放一份变量副本,也就是说一个线程可以根据一个ThreadLocal对象查询到绑定在这个线程上的一个值。只要线程处于活动状态并且ThreadLocal实例可访问,那么每个线程都拥有对其本地线程副本的隐式引用变量一个线程消失后,它的所有副本线程局部实例受垃圾回收(除非其他存在对这些副本的引用)
一般用的比较多的是
ThreadLocal.get: 获取ThreadLocal中当前线程共享变量的值。
ThreadLocal.set: 设置ThreadLocal中当前线程共享变量的值。
ThreadLocal.remove: 移除ThreadLocal中当前线程共享变量的值。
ThreadLocal.initialValue: ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回此方法值。

package com.ljessie.sinopsis.communication;

public class ThreadLocalDemo {
    
    static ThreadLocal<Integer> num = new ThreadLocal<Integer>();
    
    /**
     * 自增并打印num
     */
    private void create() {
        Integer myNum = num.get();
        myNum++;
        System.out.println(Thread.currentThread().getName()+"------>"+myNum);
        num.set(myNum);
    }
    
    public static void main(String[] args) {
        
        ThreadLocalDemo demo = new ThreadLocalDemo();
        for (int i = 1; i < 3; i++) {
            int finalI = i;
            new Thread() {
                public void run() {
                    num.set(0);
                    while(true) {
                        
                        demo.create();
                        try {
                            Thread.sleep(finalI*1000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
        }
    }

}

相关文章

  • ios 多线程的故事4

    线程间通信 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个...

  • Android 面试常问知识

    Q1:线程间的通信进程间通信的几种方式进程间通信方式详解Q2:线程安全SharePreferences 是否线程安...

  • iOS进程间通信

    线程间通信 :通过performSelector系列的方法 可以实现 各种线程间的通信(通信 :调用与传参)进程间...

  • 线程间通信

    线程间通信就是子线程和主线程之间的通信

  • 《iOS高级开发之多线程编程之二》

    线程间的通信 在一个进程中,线程往往不是孤立存在的,多个线程之间经常进行通信,称为线程间通信。 NSThread ...

  • 多线程之iOS线程间通信

    什么叫做线程间通信在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传...

  • 2.Java内存模型

    1.java并发编程的线程间通信及线程间如何同步线程间通信分为:共享内存,消息传递。线程间同步:共享内存是代码指定...

  • 8.2 线程通信

    线程通信 简介:线程间通信是指多个线程间等待与唤醒的一个交互; 1.JDK5之前传统线程的通信方式,使用...

  • iOS开发多线程--线程通信

    线程之间的通信 简单说明线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信。 线程间通...

  • (七)iOS开发之多线程—多线程之间通信

    一.线程间通信 1.什么叫做线程间通信 在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信。 2....

网友评论

      本文标题:线程间的通信

      本文链接:https://www.haomeiwen.com/subject/daagthtx.html