您的位置:首页 > 大数据 > 人工智能

多线程之线程通信摘要

2018-01-07 19:46 267 查看
首先我们要知道进程之间的通讯方式有哪些?

#管道( 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 P {

private Object lock;

P(Object lock) {
this.lock = lock;
}

public void setValue() {

try {
synchronized (lock) {
if (!ValueObject.value.equals("")) {
lock.wait();
}
String value = System.currentTimeMillis() + "_" + System.nanoTime();
System.out.println("set value = " + value);
ValueObject.value = value;
lock.notify();
System.out.println("p notify");
}

} catch (Exception e) {
e.printStackTrace();
}
}

}
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.
4000
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 R
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多线程编程核心技术 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息