java--线程间的通信

参考书籍《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线程销毁后再继续执行。

猜你喜欢

转载自blog.csdn.net/lalalahaitang/article/details/81269599