多线程之线程通信摘要

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

管道( 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多线程编程核心技术

文章目录
-----------------------
最新评论

[评论][COMMENTS]