Synchronized关键字与线程通信

一.等待/通知机制
1.通过wait/notify实现等待/通知机制
wait():可以使调用该方法的线程释放共享资源的锁,然后从运行状态退出,进入等待队列,直到被再次唤醒
notify():可以随机唤醒等待队列中等待同一共享资源的一个线程,并使该线程退出等待队列,进入可运行状态,也就是notify()方法仅通知一个线程,且随机
notifyAll():可以使所有正在等待队列中等待同一共享资源的全部线程从等待状态退出,进入可运行状态

在多线程程序中,单个线程可能会需要满足某些逻辑条件才能继续运行。当线程所要求的条件不满足时,线程进入等待状态,等待由于其他线程的运行而使条件得到满足;其他线程则负责在合适的时机发出通知来唤醒处于等待状态的线程。对于这种场景,可以使用while循环和volatile变量来处理。但是这种做法的本质是让线程处于忙等待的状态,并通过轮询的方式来判断条件是否满足。处于忙等待的线程仍然占用CPU时间,对性能造成影响。更好的做法是使用Object类提供的wait、notify和notifyAll

例1:使用wait/notify实现等待/通知机制

public class WaitAndNotify {
    static String obj="obj";

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        WaitAndNotify waitAndNotify=new WaitAndNotify();
        Runnable thread1=new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                synchronized(obj){
                    System.out.println("begin wait() ThreadName="+Thread.currentThread().getName());
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println("end wait() ThreadName="+Thread.currentThread().getName());
                }

            }
        };
        Runnable thread2=new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                synchronized (obj){
                    System.out.println("begin wait() ThreadName="+Thread.currentThread().getName());
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }                   
                    System.out.println("end wait() ThreadName="+Thread.currentThread().getName());
                }

            }
        };
        (new Thread(thread1)).start();
        (new Thread(thread2)).start();
        synchronized(obj){
            obj.notify();
        }

    }

}

运行结果:
begin wait() ThreadName=Thread-0
begin wait() ThreadName=Thread-1
end wait() ThreadName=Thread-0

例2:使用wait/notifyAll实现等待/通知机制
将例1中的notify换成notifyAll

synchronized(obj){
            obj.notifyAll();
        }

运行结果:
begin wait() ThreadName=Thread-0
begin wait() ThreadName=Thread-1
end wait() ThreadName=Thread-1
end wait() ThreadName=Thread-0

二.通过管道进行线程间通信
在java语言中提供了一种特殊的流,管道流,用于在不同线程间直接传送数据,一个线程发送数据到输出管道,另一个线程从输入管道中读取数据
在javaJDK中提供了4个类来使线程间可以通信:
1)字节流:PipedInputStream和PipedOutputStream
2)字符流:PipedReader和PipedWriter

1.字节流
例1:使用管道字节流实现线程通信

//写
import java.io.IOException;
import java.io.PipedOutputStream;

public class WriteData extends Thread {
    PipedOutputStream out;
    public WriteData(PipedOutputStream out){
        this.out=out;
    }

    public void writeMethod(PipedOutputStream out) throws IOException{
        System.out.println("write:");
        for(int i=0;i<50;i++){
            String outData=""+(i+1);
            out.write(outData.getBytes());
            System.out.print(outData);
        }
        out.close();
        System.out.println();
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        try {
            writeMethod(out);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


}
//读
import java.io.IOException;
import java.io.PipedInputStream;

public class ReadData extends Thread {
    PipedInputStream in;
    public ReadData(PipedInputStream in){
        this.in=in;

    }
    public void readMethod(PipedInputStream in) throws IOException{
        byte[] b=new byte[20];
        int readLength=in.read(b);
        while(readLength!=-1){
            String newData=new String(b,0,readLength);
            System.out.println("Read:");
            System.out.println(newData);
            readLength=in.read(b);
        }
        in.close();
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        try {
            this.readMethod(in);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}
//测试程序
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class Main {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        PipedOutputStream out=new PipedOutputStream();
        PipedInputStream in=new PipedInputStream();
        out.connect(in);
        WriteData write=new WriteData(out);
        ReadData read=new ReadData(in);
        write.start();
        read.start();

    }

}

运行结果:
write:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
Read:
12345678910111213141
Read:
51617181920212223242
Read:
52627282930313233343
Read:
53637383940414243444
Read:
54647484950

2.字符流
只需要将PipedInputStream和PipedOutputSteam对象变成PipedReader和PIpedWriter对象即可

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值