美文网首页
同步模式之顺序控制

同步模式之顺序控制

作者: 抬头挺胸才算活着 | 来源:发表于2020-03-16 22:01 被阅读0次
    1. 固定运行顺序
      比如,必须先 2 后 1 打印

    1.1 wait notify 版

        // 用来同步的对象
        static Object obj = new Object();
        // t2 运行标记, 代表 t2 是否执行过
        static boolean t2runed = false;
    
        public static void main(String[] args) {
            Thread t1 = new Thread(() -> {
                synchronized (obj) {
                    // 如果 t2 没有执行过
                    while (!t2runed) {
                        try {
                            // t1 先等一会
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                System.out.println(1);
            });
            Thread t2 = new Thread(() -> {
                System.out.println(2);
                synchronized (obj) {
                    // 修改运行标记
                    t2runed = true;
                    // 通知 obj 上等待的线程(可能有多个,因此需要用 notifyAll)
                    obj.notifyAll();
                }
            });
            t1.start();
            t2.start();
        }
    

    1.2 Park Unpark 版

    Thread t1 = new Thread(() -> {
    try { Thread.sleep(1000); } catch (InterruptedException e) { }
    // 当没有『许可』时,当前线程暂停运行;有『许可』时,用掉这个『许可』,当前线程恢复运行
    LockSupport.park();
    System.out.println("1");
    });
    Thread t2 = new Thread(() -> {
    System.out.println("2");
    // 给线程 t1 发放『许可』(多次连续调用 unpark 只会发放一个『许可』)
    LockSupport.unpark(t1);
    });
    t1.start();
    t2.start();
    
    1. 交替输出
      线程 1 输出 a 5 次,线程 2 输出 b 5 次,线程 3 输出 c 5 次。现在要求输出 abcabcabcabcabc 怎么实现.
        class SyncWaitNotify {
            private int flag;
            private int loopNumber;
            public SyncWaitNotify(int flag, int loopNumber) {
                this.flag = flag;
                this.loopNumber = loopNumber;
            }
            public void print(int waitFlag, int nextFlag, String str) {
                for (int i = 0; i < loopNumber; i++) {
                    synchronized (this) {
                        while (this.flag != waitFlag) {
                            try {
                                this.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.print(str);
                        flag = nextFlag;
                        this.notifyAll();
                    }
                }
            }
        }
    
    SyncWaitNotify syncWaitNotify = new SyncWaitNotify(1, 5);
    new Thread(() -> {
      syncWaitNotify.print(1, 2, "a");
    }).start();
    new Thread(() -> {
      syncWaitNotify.print(2, 3, "b");
    }).start();
    new Thread(() -> {
      syncWaitNotify.print(3, 1, "c");
    }).start();
    

    Lock条件变量版

        class AwaitSignal extends ReentrantLock {
            public void start(Condition first) {
                this.lock();
    
                try {
                    log.debug("start");
                    first.signal();
                } finally {
                    this.unlock();
                }
            }
            public void print(String str, Condition current, Condition next) {
                for (int i = 0; i < loopNumber; i++) {
                    this.lock();
                    try {
                        current.await();
                        log.debug(str);
                        next.signal();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        this.unlock();
                    }
                }
            }
            // 循环次数
            private int loopNumber;
            public AwaitSignal(int loopNumber) {
                this.loopNumber = loopNumber;
            }
        }
    
    AwaitSignal as = new AwaitSignal(5);
    Condition aWaitSet = as.newCondition();
    Condition bWaitSet = as.newCondition();
    Condition cWaitSet = as.newCondition();
    new Thread(() -> {
    as.print("a", aWaitSet, bWaitSet);
    }).start();
    new Thread(() -> {
    as.print("b", bWaitSet, cWaitSet);
    }).start();
    new Thread(() -> {
    as.print("c", cWaitSet, aWaitSet);
    }).start();
    as.start(aWaitSet);
    

    2.3 Park

    class SyncPark {
    private int loopNumber;
    private Thread[] threads;
    public SyncPark(int loopNumber) {
    this.loopNumber = loopNumber;
    }
    public void setThreads(Thread... threads) {
    this.threads = threads;
    }
    public void print(String str) {
    for (int i = 0; i < loopNumber; i++) {
    LockSupport.park();
    System.out.print(str);
    LockSupport.unpark(nextThread());
    }
    }
    private Thread nextThread() {
    Thread current = Thread.currentThread();
    int index = 0;
    for (int i = 0; i < threads.length; i++) {
    if(threads[i] == current) {
    index = i;
    break;
    }
    }
    if(index < threads.length - 1) {
    return threads[index+1];
    } else {
    return threads[0];
    }
    }
    public void start() {
    for (Thread thread : threads) {
    thread.start();
    }
    LockSupport.unpark(threads[0]);
    }
    }
    
    SyncPark syncPark = new SyncPark(5);
    Thread t1 = new Thread(() -> {
    syncPark.print("a");
    });
    Thread t2 = new Thread(() -> {
    syncPark.print("b");
    });
    Thread t3 = new Thread(() -> {
    syncPark.print("c\n");
    });
    syncPark.setThreads(t1, t2, t3);
    syncPark.start();
    

    相关文章

      网友评论

          本文标题:同步模式之顺序控制

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