A simple way to communicate between threads is to use synchronized to synchronize a certain data flag. One thread is responsible for setting the flag, and the other thread is responsible for loop detection of the flag. The advantage of this method is convenient, but it needs rotation training and consumes too much cpu time. It's said that you can use sleep once every millisecond, so you don't need to consume too much cpu time. This method is good. If there is no obvious low latency requirement, it's really OK. However, if there is a time requirement for sleep, it is better to use the thread communication mechanism provided by java as soon as possible rather than a fixed time.
Thread communication mainly uses notify and wait methods.
By calling the wait method of the same object, the current thread can enter the waiting state. By calling the notify method of the object, a random thread entering the waiting state on the object can be awakened to continue working. notifyall calls all.
There is such a code that combines synchronized and notify/wait to make a simple Lock:
package Thread_03; import java.util.List; import java.util.Optional; import java.util.ArrayList; import java.util.Collections; import java.util.concurrent.TimeoutException; import static java.lang.Thread.currentThread; import static java.lang.System.currentTimeMillis; /* * wait and notify for objects with synchronized and Object. To develop a streamlined lock. * */ interface Lock { void lock() throws InterruptedException; void lock(long mills) throws InterruptedException,TimeoutException; void unlock(); List<Thread> getBlockedThreads(); } class BooleanLock implements Lock { private Thread currentThread; private boolean locked = false; private final List<Thread> blockedList = new ArrayList<>(); @Override public void lock() throws InterruptedException { synchronized(this) { while(locked) { if(!blockedList.contains(currentThread())) blockedList.add(currentThread()); this.wait(); } blockedList.remove(currentThread()); this.locked = true; this.currentThread = currentThread(); } } @Override public void lock(long mills) throws InterruptedException, TimeoutException { synchronized(this) { if(mills<0) { this.lock(); } else { long remainingMills = mills; long endMills = currentTimeMillis() + remainingMills; while(locked) { if(remainingMills <= 0) throw new TimeoutException("can not get lock : wait time out"); if(!blockedList.contains(currentThread())) blockedList.add(currentThread()); this.wait(remainingMills); remainingMills = endMills - currentTimeMillis(); } blockedList.remove(currentThread()); this.locked = true; this.currentThread = currentThread(); } } } @Override public void unlock() { synchronized(this) { if(currentThread == currentThread()) { this.locked = false; //Optional.of("dd").ifPresent(System.out::println); this.notifyAll(); } } } @Override public List<Thread> getBlockedThreads() { return Collections.unmodifiableList(blockedList); } } public class notifyWaitStudy { }