美文网首页
线程间通信

线程间通信

作者: MisAutumn | 来源:发表于2020-06-15 15:53 被阅读0次

    1. volatile关键字实现线程之间属性的可见性

    public class TestSync {
        // 定义一个共享变量来实现通信,它需要是volatile修饰,否则线程不能及时感知
        static volatile boolean notice = false;
    
        public static void main(String[] args) {
            List<String>  list = new ArrayList<>();
            // 实现线程A
            Thread threadA = new Thread(() -> {
                for (int i = 1; i <= 10; i++) {
                    list.add("abc");
                    System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (list.size() == 5)
                        notice = true;
                }
            });
            // 实现线程B
            Thread threadB = new Thread(() -> {
                while (true) {
                    if (notice) {
                        System.out.println("线程B收到通知,开始执行自己的业务...");
                        break;
                    }
                }
            });
            // 需要先启动线程B
            threadB.start();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 再启动线程A
            threadA.start();
        }
    }
    

    2. 使用Object的notify(),notifyAll(), wait()方法实现通信。
    wait()让当前持有对象的线程释放锁进行等待。
    notify()通知在等待该对象的线程,通知后不会释放锁,要运行完同步方法后释放。
    notify()一次只随机唤醒一个线程,notifyAll()可以唤醒所有。

    public class TestSync {
        public static void main(String[] args) {
            // 定义一个锁对象
            Object lock = new Object();
            List<String>  list = new ArrayList<>();
            // 实现线程A
            Thread threadA = new Thread(() -> {
                synchronized (lock) {
                    for (int i = 1; i <= 10; i++) {
                        list.add("abc");
                        System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if (list.size() == 5)
                            lock.notify();// 唤醒B线程
                    }
                }
            });
            // 实现线程B
            Thread threadB = new Thread(() -> {
                while (true) {
                    synchronized (lock) {
                        if (list.size() != 5) {
                            try {
                                lock.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println("线程B收到通知,开始执行自己的业务...");
                    }
                }
            });
            // 需要先启动线程B
            threadB.start();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 再启动线程A
            threadA.start();
        }
    }
    

    wait()sleep()的区别
    sleep()属于Thread类中的方法,调用后线程不会释放锁,但会暂停该线程让出cpu资源。

    3. CountDownLatch
    java.util.concurrent并发包下基于AQS框架,维护了一个线程之间共享变量的状态。

    public class TestSync {
        public static void main(String[] args) {
            CountDownLatch countDownLatch = new CountDownLatch(1);
            List<String>  list = new ArrayList<>();
            // 实现线程A
            Thread threadA = new Thread(() -> {
                for (int i = 1; i <= 10; i++) {
                    list.add("abc");
                    System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (list.size() == 5)
                        countDownLatch.countDown();
                }
            });
            // 实现线程B
            Thread threadB = new Thread(() -> {
                while (true) {
                    if (list.size() != 5) {
                        try {
                            countDownLatch.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("线程B收到通知,开始执行自己的业务...");
                    break;
                }
            });
            // 需要先启动线程B
            threadB.start();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 再启动线程A
            threadA.start();
        }
    }
    

    4. ReentrantLock 结合 Condition

    ReentrantLock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    线程b: condition.await();
    线程a: condition.signal();
    

    5. LockSupport
    需要知道线程的名字

    线程b: LockSupport.park();
    线程a: LockSupport.unpark(threadB);
    

    6. 管道通信
    待补充

    转自

    相关文章

      网友评论

          本文标题:线程间通信

          本文链接:https://www.haomeiwen.com/subject/fbcgzhtx.html