首先我们要知道进程之间的通讯方式有哪些?
管道( 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]