参考书籍《java多线程核心技术》
通过轮询机制检测某一个条件实现线程之间的通信
如下,一个线程不断地往容器添加对象,另外一个线程不断地通过while语句轮询来检测条件是否到达
for(int i=0;i<10;i++) {
list.add(i+"a");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while(true) {
if(list.size()==3) {
throw new InterruptedException();
}
}
这种方式基本不会使用,如果轮询的时间间隔很小,更浪费cpu资源,如果轮询的时间间隔很大,有可能会取不到想要的数据。
等待/通知机制实现通信
wait()方法:方法wait()的作用是使当前执行代码的线程进行等待,await()方法是Object类的方法,该方法用来将当前线程置入“预处理队列”中,并且在wait()所在的代码出停止执行,直到接到通知或被中断为止。
在调用该方法之前,线程必须获取该对象的对象级别锁 ,即只能在同步方法或同步块中调用wait方法。执行该方法后,当前线程释放锁。在从该方法返回前,线程与其他线程竞争重新获得锁。
notify()方法: 调用该方法前线程也必须获取该对象的对象级别锁 。该方法用来通知那些可能等待该对象的对象锁的其他线程,注意:必须是等待同一把锁的线程才会被通知。 如果有多个线程等待,则有线程规划器随机挑选一个处在wait状态的线程,并对它发出通知。并使它获取该对象的对象及锁。
执行notify()方法后,当前线程不会马上释放对象锁,wait()状态的线程也不会马上就获取该对象锁,要等到执行notify()方法的线程将程序执行完,退出synchronize代码块后,当前线程才会释放锁。
synchronized (lock) {
for(int i=0;i<10;i++) {
list.add(i+"a");
if(list.size()==3) {
lock.notify();
}
}
}
synchronized (lock) {
if(list.size()!=3) {
lock.wait();
}
}
生产者/消费者模式实现线程之间的通信
此模式是基于wait/notify实现的。
生产者
public void setValue() {
synchronized (lock) {
if(!Value.value.equals("")) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Value.value="a";
lock.notify();
}
}
消费者
public void getValue() {
synchronized (lock) {
if(Value.value.equals("")) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Value.value="";
lock.notify();
}
}
通过管道进行线程间通信:字节流
管道流是一种特殊的流,用于在不同的线程间直接传送数据,一个线程发送数据到输出管道,另外一个线程从输入管道中读取数据,通过使用管道实现不同线程间的通信。
JDK中提供4个类
1,PipeInputStream和PipeOutputStream
2,PipeReader和PipeWriter
//写入数据
for(int i=0;i<20;i++) {
outputStream.write((i+"").getBytes());
}
outputStream.close();
//读取数据
byte[] bs=new byte[100];
int length=inputStream.read(bs);
while(length!=-1) {
System.out.println(new String(bs,0,length));
length=inputStream.read(bs);
}
//将输入管道和输出管道连接起来
PipedInputStream inputStream=new PipedInputStream();
PipedOutputStream outputStream=new PipedOutputStream();
outputStream.connect(inputStream);
join方法
如果主线程想要等待子线程执行完成之后再结束,就可以使用join方法。该方法的作用是等待线程对象毁。
public static void main(String[] args) throws IOException {
Thread thread=new Thread();
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
这时主线程会等待thread线程执行完后才会继续执行。
该方法的作用就是使所属的线程对象x正常执行完run方法中的任务,而使当前线程进行阻塞,等待x线程销毁后再继续执行。