天天看点

多线程之间的同步问题

因为之前工作中一般单线程就能解决问题,很少用到多线程,即使用到也是在一些框架源码中别人封装好的,所以一直没有太在意这个问题。

但是前两天遇到一个题目刚好是考查关于多线程之间的同步,因此也就借这个机会看了下这方面的相关知识。

相关基础知识:

在多线程中经常使用到sleep()、wait()、notify()、notifyAll()方法,有几点需要注意:

1、sleep()是属于Thread类中的,而wait()、notify()、notifyAll()则是属于Object类中的;

2、sleep()调用后程序会暂停执行指定的时间,让出cpu资源给其他线程,但是他的监控状态依然保持着,不会释放锁,当指定的时间到了又会自动恢复运行状态。而wait()不仅会让出cpu资源,还会释放锁;

3、wait() 与 notify()、notifyAll ()在执行时,必须要先获得锁,因此一般与synchronized关键字一起使用;

4、当执行notify()、notifyAll()时,会唤醒一个处于等待该 锁 的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronized修饰的代码块)后再释放锁。[notify()、notifyAll()执行后,并不立即释放锁,而是要等到执行完临界区中代码后,再释放。故,在实际编程中,我们应该尽量在线程调用notify()、notifyAll()后,立即退出临界区。即不要在notify()、notifyAll()后面再写一些耗时的代码]

上面都是一些关于线程的基础知识点,有了这些知识的铺垫,现在我们来看看题目的具体要求:

现有3个线程A、B、C,他们分别打印“早上”、“中午”、“晚上”,如何设计这三个线程之间的同步,让他们连续打印10次“早上中午晚上”的字样。

下面是小编自己敲键盘写的几行拙略的代码来实现这个功能:

package com.monkey.testthreadasync;

public class TestThreadAsync {
    private static Thread threadA;
    private static Thread threadB;
    private static Thread threadC;
    private static int count = ;
    private static int PRINT_COUNT = ;
    private static boolean flagA = true;

    public static void main(String[] args) {
        testThreadAsync();
    }

    //notify和wait方法都是object的方法,在调用这两个方法的时候应该获得锁(否则会出现 java.lang.IllegalMonitorStateException)
    //即一般与synchronized关键字一起使用
    private static void testThreadAsync() {
        Object objA = new Object();
        Object objB = new Object();
        Object objC = new Object();
        threadA = new Thread(){
            public void run() {
                while(flagA){
                    if(count>=PRINT_COUNT){
                        flagA = false;
                        continue;
                    }
                    synchronized (objA) {
                        System.out.println("早上");
                        count++;
                        try {
                            if (threadB != null && threadB.isAlive()){
                                synchronized (objB) {
                                    objB.notify();
                                }
                            }else{
                                threadB.start();
                            }
                            objA.wait();
                        }catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };

        threadB = new Thread(){
            public void run() {
                while(true){
                    synchronized (objB) {
                        System.out.println("中午");
                        if (threadC != null && threadC.isAlive()){
                            synchronized (objC) {
                                objC.notify();
                            }
                        }else{
                            threadC.start();
                        }
                        try {
                            objB.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };
        threadC = new Thread(){
            public void run() {
                while(true){
                    synchronized (objC) {
                        System.out.println("晚上");
                        synchronized (objA) {
                            objA.notify();
                        }
                        try {
                            //这里虽然前面执行了threadA.notify(),但是notify方法并不是立即释放锁,
                            //需要等待其后面的代码执行完了之后才会释放锁,因此notify后面的方法不应该执行耗时的操作
                            objC.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };

        threadA.start();
    }

}
           

打印结果如下,基本实现了题目要求的功能:

多线程之间的同步问题

如有需要改正或者优化的地方,欢迎留言讨论^^ ^^