Java concurrent programming-sequence control of synchronous mode

Sequence control of synchronous mode

For example, two threads start, you must first 打印2post 打印1.

wait notify 版

package cn.itcast.test;

import lombok.extern.slf4j.Slf4j;

@Slf4j(topic = "c.Test25")
public class Test25 {
    
    
    static final Object lock = new Object();
    // 表示 t2 是否运行过
    static boolean t2runned = false;

    public static void main(String[] args) {
    
    
        Thread t1 = new Thread(() -> {
    
    
            synchronized (lock) {
    
    
                while (!t2runned) {
    
    
                    try {
    
    
                        lock.wait();
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }
                log.debug("1");
            }
        }, "t1");


        Thread t2 = new Thread(() -> {
    
    
            synchronized (lock) {
    
    
                log.debug("2");
                t2runned = true;
                lock.notify();
            }
        }, "t2");

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

test

12:25:12.967 c.Test25 [t2] - 2
12:25:12.970 c.Test25 [t1] - 1

You can also use ReentrantLockthe awaitsum signalto achieve.

park Unpark version

As you can see, the implementation is very troublesome:

  • First of all, you need to ensure that you wait first and then notify, otherwise the wait thread will never be awakened. Therefore, the "run flag" is used to determine whether to wait
  • Second, if some interfering threads incorrectly notify the wait thread, and the condition is not met, the wait thread must be waited again. A while loop is used to solve this problem
  • Finally, the wait thread on the wakeup object needs to use notifyAll, because there may be more than one waiting thread on the "synchronization object"

You can use the park and unpark of the LockSupport class to simplify the above questions:

@Slf4j(topic = "c.Test26")
public class Test26 {
    
    
    public static void main(String[] args) {
    
    

        Thread t1 = new Thread(() -> {
    
    
            LockSupport.park();
            log.debug("1");
        }, "t1");
        t1.start();

        new Thread(() -> {
    
    
            log.debug("2");
            LockSupport.unpark(t1);
        },"t2").start();
    }
}

Alternate output in synchronous mode

Thread 1 outputs a 5 times, thread 2 outputs b 5 times, and thread 3 outputs c 5 times. Now it is required to output abcabcabcabcabc how to achieve

wait notify 版

@Slf4j(topic = "c.Test27")
public class Test27 {
    
    
    public static void main(String[] args) {
    
    
        WaitNotify wn = new WaitNotify(1, 5);
        new Thread(() -> {
    
    
            wn.print("a", 1, 2);
        }).start();
        new Thread(() -> {
    
    
            wn.print("b", 2, 3);
        }).start();
        new Thread(() -> {
    
    
            wn.print("c", 3, 1);
        }).start();
    }
}

/*
输出内容       等待标记     下一个标记
   a           1             2
   b           2             3
   c           3             1
 */
class WaitNotify {
    
    
    // 打印               a           1             2
    public void print(String str, int waitFlag, int nextFlag) {
    
    
        for (int i = 0; i < loopNumber; i++) {
    
    
            synchronized (this) {
    
    
                while(flag != waitFlag) {
    
    
                    try {
    
    
                        this.wait();
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }
                System.out.print(str);
                flag = nextFlag;
                this.notifyAll();
            }
        }
    }

    // 等待标记
    private int flag; // 2
    // 循环次数
    private int loopNumber;

    //构造方法
    public WaitNotify(int flag, int loopNumber) {
    
    
        this.flag = flag;
        this.loopNumber = loopNumber;
    }
}

Output

abcabcabcabcabc

Lock condition variable version

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Test30 {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        AwaitSignal awaitSignal = new AwaitSignal(5);
        Condition a = awaitSignal.newCondition();
        Condition b = awaitSignal.newCondition();
        Condition c = awaitSignal.newCondition();
        new Thread(() -> {
    
    
            awaitSignal.print("a", a, b);
        }).start();
        new Thread(() -> {
    
    
            awaitSignal.print("b", b, c);
        }).start();
        new Thread(() -> {
    
    
            awaitSignal.print("c", c, a);
        }).start();

        Thread.sleep(1000);
        awaitSignal.lock();
        try {
    
    
            System.out.println("开始...");
            a.signal();
        } finally {
    
    
            awaitSignal.unlock();
        }

    }
}

class AwaitSignal extends ReentrantLock{
    
    
    private int loopNumber;

    public AwaitSignal(int loopNumber) {
    
    
        this.loopNumber = loopNumber;
    }
    //            参数1 打印内容, 参数2 进入哪一间休息室, 参数3 下一间休息室
    public void print(String str, Condition current, Condition next) {
    
    
        for (int i = 0; i < loopNumber; i++) {
    
    
            lock();
            try {
    
    
                //使当前线程等待,直到发出信号或中断。与此条件相关联的锁被原子释放,
                //  当前线程出于线程调度目的而被禁用,并处于休眠状态,直到发生四种情况之一
                current.await();
                //打印
                System.out.print(str);
                next.signal();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            } finally {
    
    
                unlock();
            }
        }
    }
}

Output

abcabcabcabcabc

park Unpark version

import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.LockSupport;

@Slf4j(topic = "c.Test31")
public class Test31 {
    
    

    static Thread t1;
    static Thread t2;
    static Thread t3;
    public static void main(String[] args) {
    
    
        ParkUnpark pu = new ParkUnpark(5);
        t1 = new Thread(() -> {
    
    
            pu.print("a", t2);
        });
        t2 = new Thread(() -> {
    
    
            pu.print("b", t3);
        });
        t3 = new Thread(() -> {
    
    
            pu.print("c", t1);
        });
        t1.start();
        t2.start();
        t3.start();

        LockSupport.unpark(t1);
    }
}

class ParkUnpark {
    
    
    public void print(String str, Thread next) {
    
    
        for (int i = 0; i < loopNumber; i++) {
    
    
            LockSupport.park();
            System.out.print(str);
            LockSupport.unpark(next);
        }
    }

    private int loopNumber;

    public ParkUnpark(int loopNumber) {
    
    
        this.loopNumber = loopNumber;
    }
}

Output

abcabcabcabcabc

Guess you like

Origin blog.csdn.net/e891377/article/details/109158511