Java线程通信方式

一. 线程状态

043426c2200abdd8ad7ea8a86076e47c_682x511.png@900-0-90-f.png

二. 线程通信

1. volatile关键字

关键字volatile可以用来修饰字段(成员变量),就是告知程序任何对该变量的访问均需要从共享内存中获取,而对它的改变必须同步刷新回共享内存,它能保证所有线程对变量访问的可见性。
定义一个表示程序是否运行的成员变量boolean on=true,那么另一个线程可能对它执行关闭动作(on=false),这里涉及多个线程对变量的访问,因此需要将其定义成为volatile boolean on=true,这样其他线程对它进行改变时,可以让所有线程感知到变化

2. synchronized关键字

关键字synchronized可以修饰方法或者以同步块的形式来进行使用,它主要确保多个线程
在同一个时刻,只能有一个线程处于方法或者同步块中,它保证了线程对变量访问的可见性
和排他性。

3. 等待/通知机制

轮询方式:简单的办法是让消费者线程不断地循环检查变量是否符合预期,如下面代码所示,在
while循环中设置不满足的条件,如果条件满足则退出while循环,从而完成消费者的工作。

while (value != desire) {
Thread.sleep(1000);
} doSomething();

缺点:
1)难以确保及时性。在睡眠时,基本不消耗处理器资源,但是如果睡得过久,就不能及时
发现条件已经变化,也就是及时性难以保证。
2)难以降低开销。如果降低睡眠的时间,比如休眠1毫秒,这样消费者能更加迅速地发现
条件变化,但是却可能消耗更多的处理器资源,造成了无端的浪费

Wait/Notify机制:

483d18f170d19f7c45bbd270c181f448_695x508.png@900-0-90-f.png

等待方遵循原则:
1)获取对象的锁。
2)如果条件不满足,那么调用对象的wait()方法,被通知后仍要检查条件。
3)条件满足则执行对应的逻辑。

synchronized(对象) {
while(条件不满足) {
对象.wait();
}
对应的处理逻辑
}

通知方遵循原则:
1)获得对象的锁。
2)改变条件。
3)通知所有等待在对象上的线程。

synchronized(对象) {
改变条件
对象.notifyAll();
}

4. 管道输入/输出流

管道:用于线程之间的数据传输,而传输的媒介为内存。4种具体实现:PipedOutputStream、PipedInputStream、PipedReader和PipedWriter,前两种面向字节,而后两种面向字符。

public class Piped {
    public static void main(String[] args) throws Exception {
        PipedWriter out = new PipedWriter();
        PipedReader in = new PipedReader();
        // 将输出流和输入流进行连接,否则在使用时会抛出IOException
        out.connect(in);
        Thread printThread = new Thread(new Print(in), "PrintThread");
        printThread.start();
        int receive = 0;
        try {
            while ((receive = System.in.read()) != -1) {
                out.write(receive);
            }
        } finally {
            out.close();
        }
    }
    static class Print implements Runnable {
        private PipedReader in;
        public Print(PipedReader in) {
            this.in = in;
        }
        public void run() {
            int receive = 0;
            try {
                while ((receive = in.read()) != -1) {
                    System.out.print((char) receive);
                }
            } catch (IOException ex) {
            }
        }
    }
}

5. Thread.join()

一个线程A执行了thread.join()语句,其含义是:当前线程A等待thread线程终止之后才从thread.join()返回

6. ThreadLocal

数据结构:Thread->ThreadLocalMap{key:ThreadLocal,value:ThreadLocalValue}

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        //Thread持有ThreadLocalMap为空,ThreadLocal作为key插入Map
        map.set(this, value);
    else
        //Thread持有ThreadLocalMap为空,创建Map对象
        createMap(t, value);
}

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        //ThreadLocal为key,获取ThreadLocal所处Map位置,并返回对应位置的值
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容