There are three things in this world that no one can take away: one is the food in the stomach, the other is the dream hidden in the heart, and the third is the book that is read into the brain
- Analyze the topic. Two threads need to be used to alternately print odd and even numbers.
- Use synchronization locks to solve this problem
- Use semaphores to achieve alternate printing
- Define two semaphores, one odd semaphore and one even semaphore, both initialized to 1
- Use the even numbered semaphore first, because the odd number should be started first, and then released after the odd number is printed
Semaphore implementation
- Specific implementation ideas:
- Define two semaphores, one odd semaphore and one even semaphore, both initialized to 1
- Use the even numbered semaphore first, because the odd number should be started first, and then released after the odd number is printed
- The specific process is to subtract even-numbered semaphores for the first time, and use odd-numbered semaphores after odd-numbered threads are printed. Then release the even number of semaphores and cycle like this
copyimport java.util.concurrent.Semaphore; /** * @ClassName AlternatePrinting * @Author yunlogn * @Date 2019/5/21 * @Description Print odd and even numbers alternately */ public class AlternatePrinting { static int i = 0; public static void main(String[] args) throws InterruptedException { Semaphore semaphoreOdd = new Semaphore(1); Semaphore semaphoreEven = new Semaphore(1); semaphoreOdd.acquire(); //Let the odd number wait for the start first, so first subtract the even numbered semaphore and wait for the odd numbered thread to release SemaphorePrintEven semaphorePrintEven = new SemaphorePrintEven(semaphoreOdd, semaphoreEven); Thread t1 = new Thread(semaphorePrintEven); t1.start(); SemaphorePrintOdd semaphorePrintOdd = new SemaphorePrintOdd(semaphoreOdd, semaphoreEven); Thread t2 = new Thread(semaphorePrintOdd); t2.start(); } /** * Implemented using semaphores */ static class SemaphorePrintOdd implements Runnable { private Semaphore semaphoreOdd; private Semaphore semaphoreEven; public SemaphorePrintOdd(Semaphore semaphoreOdd, Semaphore semaphoreEven) { this.semaphoreOdd = semaphoreOdd; this.semaphoreEven = semaphoreEven; } @Override public void run() { try { semaphoreOdd.acquire();//Obtain the semaphore semaphoreOdd was acquired the semaphore during initialization, so it is blocked here, so the following odd-numbered threads will be executed first while (true) { i++; if (i % 2 == 0) { System.out.println("Even threads:" + i); semaphoreEven.release();//Release the even-numbered semaphore to unblock the odd-numbered thread //Apply again to obtain the even-numbered semaphore, because it has been obtained before, if there is no odd-numbered thread to release, then it will always be blocked here, waiting for the odd-numbered thread to release semaphoreOdd.acquire(); } } } catch (InterruptedException e) { e.printStackTrace(); } } } static class SemaphorePrintEven implements Runnable { private Semaphore semaphoreOdd; private Semaphore semaphoreEven; public SemaphorePrintEven(Semaphore semaphoreOdd, Semaphore semaphoreEven) { this.semaphoreOdd = semaphoreOdd; this.semaphoreEven = semaphoreEven; } @Override public void run() { try { semaphoreEven.acquire(); while (true) { i++; if (i % 2 == 1) { System.out.println("Odd threads:" + i); semaphoreOdd.release(); //Release the odd semaphore to unblock the even thread //Block here, waiting for the even thread to release the semaphore //To apply for the odd semaphore again, you need to wait for the even thread to finish executing and then release the semaphore, otherwise it will block semaphoreEven.acquire(); } } } catch (Exception ex) {} } } }
- It should be noted that if a thread is abnormally interrupted before it is released in time, it will cause another thread to wait all the time, resulting in a deadlock. Although this exception is not within the scope of this question, you can use finally to wrap and release lock resources
genlock print
- Let two threads use the same lock. Alternately execute .
- Determine whether it is an odd number. If it is an odd number, enter the odd thread to print and add one. The thread then releases the lock resource. and then make the thread wait
- Determine whether it is an even number, if it is an even number, enter the even thread to print and add one. The thread then releases the lock resource. and then make the thread wait
copyimport java.util.concurrent.atomic.AtomicInteger; /** * @ClassName AlternatePrinting * @Author yunlogn * @Date 2019/5/21 * @Description Print odd and even numbers alternately */ public class AlternatePrinting { public static AtomicInteger atomicInteger = new AtomicInteger(1); public static void main(String[] args) throws InterruptedException { Thread a=new Thread(new AThread()); Thread b=new Thread(new BThread()); a.start(); b.start(); } public static class AThread implements Runnable { @Override public void run() { while (true) { synchronized (atomicInteger) { if (atomicInteger.intValue() % 2 != 0) { System.out.println("odd number of threads:" + atomicInteger.intValue()); atomicInteger.getAndIncrement(); // An odd number of threads releases the lock resource atomicInteger.notify(); try { atomicInteger.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { try { // odd number of threads waiting atomicInteger.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } } public static class BThread implements Runnable { @Override public void run() { while (true){ synchronized (atomicInteger){ if(atomicInteger.intValue() %2== 0 ){ System.out.println("even thread:"+ atomicInteger.intValue()); atomicInteger.getAndIncrement(); // Even threads release lock resources atomicInteger.notify(); try { atomicInteger.wait(); } catch (InterruptedException e) { e.printStackTrace(); } }else{ try { // Even threads wait atomicInteger.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } } }
a simpler way of writing
copypublic class TheadTest { public static void main(String[] args) { PrintDigitThread print1 = new PrintDigitThread((i) -> i % 2 == 1, "thread1"); PrintDigitThread print2 = new PrintDigitThread((i) -> i % 2 == 0, "thread2"); print1.start(); print2.start(); } } class ShareData { public static final AtomicInteger atomicInt = new AtomicInteger(0); } class PrintDigitThread extends Thread { private Predicate<Integer> predicate; public PrintDigitThread(Predicate<Integer> predicate, String name) { this.predicate = predicate; this.setName(name); } @Override public void run() { int v = ShareData.atomicInt.get(); while (v < 100) { synchronized (ShareData.atomicInt) { v = ShareData.atomicInt.get(); if (predicate.test(v)) { System.out.println(Thread.currentThread().getName() + ":" + v); ShareData.atomicInt.incrementAndGet(); try { ShareData.atomicInt.notify(); } catch (Exception ex) { } } else { try { ShareData.atomicInt.wait(); } catch (Exception ex) { } } } } } }