美文网首页concurrent
多线程之线程通信摘要

多线程之线程通信摘要

作者: 南乡清水 | 来源:发表于2018-03-04 22:07 被阅读74次

    首先我们要知道进程之间的通讯方式有哪些?

    管道( pipe ) #消息队列( message queue ) #共享内存( shared memory ) :#套接字( socket ) 等等--

    线程的通讯方式:

    1 wait/notify 机制

    wait()方法和notify()方法是Object类提供的方法,而在使用的条件就是当前线程必须有自己的监听器

    否则就是抛出异常,我们可以使用jvm提供的内置锁 synchronized 关键字来配合使用;注意如果有多个

    线程等待,当某一线程发起唤醒操作,会随机唤醒一个线程,而非所有线程,如果想唤醒所有线程,可以使用

    notifyAll()方法

    下面是 启动一个等待线程和一个通知线程的例子

    public class MyThread1 extends Thread {  
      
        private Object lock;  
      
        public MyThread1(Object lock) {  
            this.lock = lock;  
        }  
      
        @Override  
        public void run() {  
            try {  
                synchronized (lock) {  
                    System.out.println("wait start time = " + System.currentTimeMillis());  
                    lock.wait();  
                    System.out.println("wait end time = " + System.currentTimeMillis());  
                }  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
    
    public class MyThread2 extends Thread {  
      
        private Object lock;  
      
        public MyThread2(Object lock) {  
            this.lock = lock;  
        }  
      
        @Override  
        public void run() {  
            try {  
                synchronized (lock) {  
                    System.out.println("notify start time = " + System.currentTimeMillis());  
                    lock.notify();  
                    System.out.println("notify end time = " + System.currentTimeMillis());  
                }  
      
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
    }  
    
    
    public class Test1 {  
      
        public static void main(String[] args) throws Exception {  
            Object lock = new Object();  
            MyThread1 thread1 = new MyThread1(lock);  
            thread1.start();  
            TimeUnit.SECONDS.sleep(3);  
            MyThread2 thread2 = new MyThread2(lock);  
            thread2.start();  }
    }
    

    先启动一个等待线程,然后启动唤醒线程

    测试结果如下:
    wait start time = 1515326744453
    notify start time = 1515326747453
    notify end time = 1515326747453
    wait end time = 1515326747453

    这样两线程之间就完成了通信,代码的关键是注册了同一把锁,在这个对象锁中我们可以理解有两种队列,即 等待队列和就绪队列,对象调用wait方法,则标记线程信息进入等待队列并释放锁,调用notify方法则 队列中的线程进入就绪队列竞争获取锁,这种方式其实可以理解为是内存共享

    2生产者/消费者模式

    比如常用的消息队列bolckingqueue都是基于生产者消费者模型实现的。其本质上是基于wait/notify机制实现的

    例如我们通过wait/notify的方式实现这种模式

    public class C {  
      
        private Object lock;  
      
        C(Object lock) {  
            this.lock = lock;  
      
        }  
      
        public void getValue() {  
      
            try {  
                synchronized (lock) {  
                    if (ValueObject.value.equals("")) {  
                        lock.wait();  
                    }  
                    System.out.println("get value = " + ValueObject.value);  
                    ValueObject.value = "";  
                    lock.notify();  
                    System.out.println("c notify");  
                }  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
      
    }  
    
    public class ThreadP extends Thread {  
      
        private P p;  
      
        public ThreadP(P p) {  
            this.p = p;  
        }  
      
        @Override public void run() {  
            while (true) {  
                p.setValue();  
            }  
        }  
    }  
    
    public class ThreadC extends Thread {  
      
        private C c;  
      
        public ThreadC(C c) {  
            this.c = c;  
        }  
      
        @Override public void run() {  
            while (true){  
                c.getValue();  
            }  
        }  
    }  
    
    public class ValueObject {  
      
        public static String value = "";  
      
    }  
    
    public class Test {  
      
        public static void main(String[] args) {  
            String lock = new String("");  
            P p = new P(lock);  
            C c = new C(lock);  
            ThreadP threadP = new ThreadP(p);  
            ThreadC threadC = new ThreadC(c);  
            threadP.start();  
            threadC.start();  
      
        }  
    

    结果是:会不停读取生存者线程中的数据,并把它变成空字符串

    这是1对1的生产者消费者模型简单实现

    3 管道

    java中有提供管道流这种api ,重点是四个类

    PipedInputStream
    PipedOutputStream
    PipedWriter
    PipedRead

    上述四个类可用于管道字节流和字符流的实现,
    我们通过字符流的方式 实现线程之间的通信
    如下

    public class WriteData {  
      
        public void writeMethod(PipedWriter writer) {  
      
            try {  
                StringBuilder data = new StringBuilder();  
                System.out.println("write : " );  
                for (int i = 0; i < 20; i++) {  
                    data.append(i);  
                    writer.write("" + i);  
                }  
                System.out.println("write data = " + data);  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
      
    }  
    
    public class ReadData {  
      
        public void readMethod(PipedReader reader) {  
            StringBuilder d = new StringBuilder();  
            try {  
                System.out.println("read : ");  
                char[] buffer = new char[5];  
                int readLength;  
      
                while ((readLength = reader.read(buffer)) !=-1) {  
                    String data = new String(buffer, 0 ,readLength);  
                    d.append(data);  
                }  
                reader.close();  
            } catch (Exception e) {  
      
            }finally {  
                System.out.println("result data = " + d);  
            }  
        }  
      
    }  
    
    public class Run {  
      
        public static void main(String[] args) throws Exception {  
            WriteData writeData = new WriteData();  
            ReadData readData = new ReadData();  
            PipedReader reader = new PipedReader();  
            PipedWriter writer = new PipedWriter();  
           // reader.connect(writer);  
            writer.connect(reader);  
            new Thread(() -> writeData.writeMethod(writer)).start();  
            TimeUnit.SECONDS.sleep(2);  
            new Thread(() -> readData.readMethod(reader)).start();  
      
        }  
      
    

    结果如下

    write :
    write data = 012345678910111213141516171819
    read :
    result data = 012345678910111213141516171819

    线程之间完成了通信

    其他线程通信方式比如 java socket方式等也可以实现,这里不再叙述

    知识点来源: java多线程编程核心技术

    相关文章

      网友评论

        本文标题:多线程之线程通信摘要

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