java线程间通信笔记

使用 volatile 关键字

public class TestSync {
    // 定义一个共享变量来实现通信,它需要是volatile修饰,否则线程不能及时感知
    static volatile boolean notice = false;

    public static void main(String[] args) {
        List  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();
    }
}

运行结果:

线程A向list中添加一个元素,此时list中的元素个数为:1
线程A向list中添加一个元素,此时list中的元素个数为:2
线程A向list中添加一个元素,此时list中的元素个数为:3
线程A向list中添加一个元素,此时list中的元素个数为:4
线程A向list中添加一个元素,此时list中的元素个数为:5
线程A向list中添加一个元素,此时list中的元素个数为:6
线程B收到通知,开始执行自己的业务...
线程A向list中添加一个元素,此时list中的元素个数为:7
线程A向list中添加一个元素,此时list中的元素个数为:8
线程A向list中添加一个元素,此时list中的元素个数为:9
线程A向list中添加一个元素,此时list中的元素个数为:10

Process finished with exit code 0

至于为什么个数为6时,才运行线程B,当list.size() == 5,notice变为true,线程A此时并未停止循环,而是再次执行了i=6的循环

使用Object类的wait() 和 notify() 方法

public class TestSync {
    public static void main(String[] args) {
        // 定义一个锁对象
        Object lock = new Object();
        List  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();
    }
}

输出:

线程A向list中添加一个元素,此时list中的元素个数为:1
线程A向list中添加一个元素,此时list中的元素个数为:2
线程A向list中添加一个元素,此时list中的元素个数为:3
线程A向list中添加一个元素,此时list中的元素个数为:4
线程A向list中添加一个元素,此时list中的元素个数为:5
线程A向list中添加一个元素,此时list中的元素个数为:6
线程A向list中添加一个元素,此时list中的元素个数为:7
线程A向list中添加一个元素,此时list中的元素个数为:8
线程A向list中添加一个元素,此时list中的元素个数为:9
线程A向list中添加一个元素,此时list中的元素个数为:10
线程B收到通知,开始执行自己的业务...

线程A发出notify()唤醒通知之后,依然是走完了自己线程的业务之后,线程B才开始执行,这也正好说明了,notify()方法不释放锁
notify正确的使用方法:不要在notify后再执行业务代码

public class WaitNotify {
    // 状态锁
    private static Object lock = new Object();
    private static Integer i = 0;

    public void odd() {
        while (i < 10) {
            synchronized (lock) {
                if (i % 2 == 1) {
                    System.out.println(Thread.currentThread().getName() + " - " + i);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    i++;
                    lock.notify();
                } else {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public void even() {
        while (i < 10) {
            synchronized (lock) {
                if (i % 2 == 0) {
                    System.out.println(Thread.currentThread().getName() + " - " + i);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    i++;
                    lock.notify();
                } else {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public static void main(String[] args) {

        final WaitNotify waitNotify = new WaitNotify();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                waitNotify.odd();
            }
        }, "线程1");
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                waitNotify.even();
            }
        }, "线程2");

        t1.start();
        t2.start();
    }
}

CountDownLatch

public class TestCountDown {
    public static void main(String[] args) {
    final CountDownLatch countDownLatch = new CountDownLatch(1);
    final List list = new ArrayList<>();
    // 实现线程A
    Thread threadA = new Thread(new Runnable() {
        @Override
        public void run() {
            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(new Runnable() {
        @Override
        public void run() {
            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();
}
}

输出:

线程A向list中添加一个元素,此时list中的元素个数为:1
线程A向list中添加一个元素,此时list中的元素个数为:2
线程A向list中添加一个元素,此时list中的元素个数为:3
线程A向list中添加一个元素,此时list中的元素个数为:4
线程A向list中添加一个元素,此时list中的元素个数为:5
线程A向list中添加一个元素,此时list中的元素个数为:6
线程B收到通知,开始执行自己的业务...
线程A向list中添加一个元素,此时list中的元素个数为:7
线程A向list中添加一个元素,此时list中的元素个数为:8
线程A向list中添加一个元素,此时list中的元素个数为:9
线程A向list中添加一个元素,此时list中的元素个数为:10

Process finished with exit code 0

countDownLatch.countDown()执行-1操作,当count=0时,会通知countDownLatch.await(),继续执行下面代码

LockSupport

public class LockSupportTest {
    public static void main(String[] args) {
        final List list = new ArrayList<>();
        // 实现线程B
        final Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                if (list.size() != 5) {
                    LockSupport.park();
                }
                System.out.println("线程B收到通知,开始执行自己的业务...");
            }
        });
        // 实现线程A
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                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)
                        LockSupport.unpark(threadB);
                }
            }
        });
        threadA.start();
        threadB.start();
    }
}

输出:

线程A向list中添加一个元素,此时list中的元素个数为:1
线程A向list中添加一个元素,此时list中的元素个数为:2
线程A向list中添加一个元素,此时list中的元素个数为:3
线程A向list中添加一个元素,此时list中的元素个数为:4
线程A向list中添加一个元素,此时list中的元素个数为:5
线程A向list中添加一个元素,此时list中的元素个数为:6
线程B收到通知,开始执行自己的业务...
线程A向list中添加一个元素,此时list中的元素个数为:7
线程A向list中添加一个元素,此时list中的元素个数为:8
线程A向list中添加一个元素,此时list中的元素个数为:9
线程A向list中添加一个元素,此时list中的元素个数为:10

Process finished with exit code 0

你可能感兴趣的:(java线程间通信笔记)