• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Java > Java多线程之通过管道线程间通信(字节流、字符流),类ThreadLocal与类InheritableThreadLocal的使用

Java多线程之通过管道线程间通信(字节流、字符流),类ThreadLocal与类InheritableThreadLocal的使用

作者:ChangWen的博客 字体:[增加 减小] 来源:互联网 时间:2017-08-27

ChangWen的博客通过本文主要向大家介绍了java,多线程,字符流等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

  在Java语言中提供了各种各样的输人/输出流Stream,使我们能够很方便地对数据进行操作,其中管道流(pipeStream)是一种特殊的流,用于在不同线程间直接传送数据。一个线程发送数据到输出管道,另一个线程从输人管道中读数据。通过使用管道,实现不同线程间的通信,而无须借助于类似临时文件之类的东西。
  在Java的JDK中提供了4个类来使线程间可以进行通信:
  1)PipedInputStream和PipedOutputStream
  2)PipedReader和PipedWriter

1、通过管道进行线程间通信:字节流/字符流

public class WriteData {
    public void writeMethod(PipedOutputStream out) { //字符流这里换成PipeWriter
        try {
            System.out.println("write :");
            for (int i=0; i<10; i++) {
                String outData = "" + (i+1);
                out.write(outData.getBytes());  //字符流这里换成out.write(outData)
                System.out.print(outData);
            }
            System.out.println();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class ReadData {
    public void readMethod(PipedInputStream input) {  //字符流这里换成PipedReader
        try {
            System.out.println("read: ");
            byte[] byteArray = new byte[20];  //字符流这里换成char
            int readLength = input.read(byteArray);  
            while (readLength != -1) {
                String newData = new String(byteArray, 0, readLength);
                System.out.println(newData);
                readLength = input.read(byteArray);
            }
            System.out.println();
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

两个自定义线程

public class ThreadWrite extends Thread {
    private WriteData write;
    private PipedOutputStream out;  //字符流这里换成PipedWriter

    public ThreadWrite(WriteData write, PipedOutputStream out) {  //字符流这里换成PipedWriter
        this.write = write;
        this.out = out;
    }
    public void run() {
        write.writeMethod(out);
    }
}
public class ThreadRead extends Thread {
    private ReadData read;
    private PipedInputStream input;  //字符流这里换成PipedRead

    public ThreadRead(ReadData read, PipedInputStream input) { //字符流这里换成PipedRead
        this.read = read;
        this.input = input;
    }
    public void run() {
        read.readMethod(input);
    }
}
public class Run {
    public static void main(String[] args) throws InterruptedException, IOException {
        WriteData writeData = new WriteData();
        ReadData readData = new ReadData();

        PipedInputStream inputStream = new PipedInputStream();   //字符流用PipedReader
        PipedOutputStream outputStream = new PipedOutputStream();  //字符流用PipedWriter

        inputStream.connect(outputStream); //这两个只能用一个
        //outputStream.connect(inputStream);

        ThreadRead threadRead = new ThreadRead(readData,inputStream);
        threadRead.start();

        Thread.sleep(2000);

        ThreadWrite threadWrite = new ThreadWrite(writeData,outputStream);
        threadWrite.start();
    }
}

read:
write :
12345678910
12345678910
  使用代码inputStream.connect(outputStream)或outputStream.connect(inputStream)的作用使两个 Stream之间产生通信链接,这样才可以进行输出输入。


二、类ThreadLocal与类InheritableThreadLocal的使用

2.1.类ThreadLocal的使用
  变量值的共享可以使用public static 变量的形式,所有的线程都使用同一个public static变量。如果想实现每一个线程都有自己的共享变量该如何解决呢?JDK中提供的类ThreadLocal正是为了解决这样的问题。
  类ThreadLocal主要解决的就是每个线程绑定自己的值,可以将ThreadLocal类比喻成全局存放数据的盒子,盒子中可以存储每个线程的私有数据。
1、方法get()与null

public class Run {
    public static ThreadLocal threadLocal = new ThreadLocal();

    public static void main(String[] args) throws InterruptedException {
        if (threadLocal.get() == null) {
            System.out.println("从未放过值。");
            threadLocal.set("我的值");
        }
        System.out.println(threadLocal.get());
    }
}

从未放过值。
我的值
  从运行结果来看,第一次调用threadLocal对象的get()方法时返回的值是null,通过调用set()方法赋值后顺利取出值并打印到控制台上。
  类Threadlocal解决的是变量在不同线程间的隔离性,也就是不同线程拥有自己的值,不同线程中的值是可以放人Threadlocal类中进行保存的。

2、验证线程变量的隔离性
  多个线程用一个ThreadLocal类

public class Tools {
    public static ThreadLocal t1 = new ThreadLocal();
}

// 两个自定义的线程
public class MyThread1 extends Thread {
    public void run() {
        try {
            for (char i='a'; i<'z'; i++) {
                Tools.t1.set("Thread1-" + i);
                System.out.println("Thread1 get value=" + Tools.t1.get());
                Thread.sleep(200);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class MyThread2 extends Thread{
    public void run() {
        try {
            for (int i=0; i<30; i++) {
                Tools.t1.set("Thread2—" + (i+1));
                System.out.println("Thread2 get value=" + Tools.t1.get());
                Thread.sleep(200);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class Run {
    public static void main(String[] args) throws InterruptedException {
        MyThread1 a = new MyThread1();
        MyThread2 b = new MyThread2();
        a.start();
        b.start();
        for (int i=0; i<33; i++) {
            Tools.t1.set("Main" + (i+1));
            System.out.println("Main get value=" + Tools.t1.get());
            Thread.sleep(200);
        }
    }
}

Main get value=Main1
Thread2 get value=Thread2—1
Thread1 get value=Thread1-a
Thread1 get value=Thread1-b
Thread2 get value=Thread2—2
Main get value=Main2
Thread1 get value=Thread1-c
Main get value=Main3
Thread2 get value=Thread2—3
……
  虽然3个线程都向t1对象中set()数据值,但每个线程还是能取出自己的数据。
  
3、解决get()返回null的问题
  重写ThreadLocal方法,得到初始值,这样第一次get不再为null

public class ThreadLocalExt extends ThreadLocal {
    @Override
    protected Object initialValue() {
        return "重写ThreadLocal方法,得到初始值,让第一次get不再为null";
    }
}
public class Run {
    public static ThreadLocalExt t1 = new ThreadLocalExt();

    public static void main(String[] args) throws InterruptedException {
       if (t1.get() == null) {
           System.out.println("从未放过值");
           t1.set("我的值");
       }
        System.out.println(t1.get());
    }
}

2.2、类InheritableThreadLocal的使用
  使用InheritableThreadLocal类可以让子线程从父线程中取得值。
1、值继承
public class InheritableThreadLocal extends ThreadLocal

public class InheritableThreadLocalExt extends InheritableThreadLocal {
    @Override
    protected Object initialValue() {
        return new Date().getTime();
    }
}

public class Tools {
    public static InheritableThreadLocalExt t1 = new InheritableThreadLocalExt();
}

public class MyThread1 extends Thread {
    public void run() {
        try {
            for (int i=0; i<5; i++) {
                System.out.println("Thread1 get value=" + Tools.t1.get());
                Thread.sleep(200);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class Run {
    public static void main(String[] args) throws InterruptedException {
        for (int i=0; i<5; i++) {
            System.out.println("    在Main线程中取值=" + Tools.t1.get());
            Thread.sleep(100);
        }
        Thread.sleep(3000);

        MyThread1 a = new MyThread1();
        a.start();
    }
}

在Main线程中取值=1462588336441
在Main线程中取值=1462588336441
在Main线程中取值=1462588336441
在Main线程中取值=1462588336441
在Main线程中取值=1462588336441
Thread1 get value=1462588336441
Thread1 get value=1462588336441
Thread1 get value=1462588336441
Thread1 get value=1462588336441
Thread1 get value=1462588336441

2、值继承再修改
  再继承的同时还可以对值进行进一步的处理(但是在使用InheritableThreadLocal类需要注意一点的是,如果子线程在取得值的同时,主线程将InheritableThreadLocal中的值更改,那么 子线程取到的值还是旧值)。修改如下

public class InheritableThreadLocalExt extends InheritableThreadLocal {
    @Override
    protected Object initialValue() {
        return new Date().getTime();
    }

    @Override
    protected Object childValue(Object parentValue) {
        return parentValue + "  重写后在子线程加的!";
    }
}

在Main线程中取值=1462588868404
在Main线程中取值=1462588868404
在Main线程中取值=1462588868404
在Main线程中取值=1462588868404
在Main线程中取值=1462588868404
Thread1 get value=1462588868404 重写后在子线程加的!
Thread1 get value=1462588868404 重写后在子线程加的!
Thread1 get value=1462588868404 重写后在子线程加的!
Thread1 get value=1462588868404 重写后在子线程加的!
Thread1 get value=1462588868404 重写后在子线程加的!

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • JavaThreadPoolExecutor线程池调度器
  • 全面掌握Java内部类
  • Java中的常用阻塞队列源码分析
  • Java虚拟机(四)垃圾收集算法
  • Java内存模型与线程
  • Java中如何优雅正确的终止线程
  • [译]深入字节码操作:使用ASM和Javassist创建审核日志
  • IntelliJIDEA平台下JNI编程(五)—本地C代码创建Java对象及引用
  • 【java总结】设计模式详解
  • Java代码中常见技术债务处理之Exception

相关文章

  • 2017-05-28深入理解Java嵌套类和内部类
  • 2017-05-28Java 网络编程socket编程等详解
  • 2017-05-28springboot + devtools(热部署)实例教程
  • 2017-05-28浅析Java 数据结构常用接口与类
  • 2017-05-28java利用java.net.URLConnection发送HTTP请求的方法详解
  • 2017-05-28Java微信公众平台开发(7) 公众平台测试帐号的申请
  • 2017-05-28Spring Boot如何使用Spring Security进行安全控制
  • 2017-05-28Java数据结构和算法之冒泡排序(动力节点Java学院整理)
  • 2017-05-28spring mvc 使用kaptcha配置生成验证码实例
  • 2017-05-28mybatis中oracle实现分页效果实例代码

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • JVM(Java虚拟机)简介(动力节点Java学院整理)
    • springboot全局异常处理详解
    • Java数据结构与算法之栈(动力节点Java学院整理)
    • Java中自动生成构造方法详解
    • Spring Boot 整合 Mybatis Annotation 注解的完整 Web 案例
    • Java 抽象类定义与方法实例详解
    • Java 线程优先级详解及实例
    • java 中链表的定义与使用方法
    • Spring与Spring boot的区别介绍
    • java数据结构与算法之桶排序实现方法详解

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有