交替打印就是要实现线程间通信,有两种方式:
1Object对象中的wait和notify(因为是交替打印,只需唤醒一个线程,所以不需要notifyAll)
1 package com.nmcc.thread; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 6 /** 7 * TODO 8 * 9 * @author nmcc 10 * @version V1.0 11 * @date 2021-08-24 08:49 12 * 13 */ 14 public class SyncRunTwo { 15 16 public static Object a_o = new Object(); 17 public static Object b_o = new Object(); 18 public static Object c_o = new Object(); 19 20 public static void main(String[] args) throws InterruptedException { 21 ExecutorService executor = Executors.newFixedThreadPool(3); 22 executor.execute(new BuszThread("C", c_o, b_o)); 23 executor.execute(new BuszThread("B", b_o, a_o)); 24 executor.execute(new BuszThread("A", a_o, c_o)); 25 Thread.sleep(1000); 26 27 synchronized (c_o){ 28 c_o.notify(); 29 } 30 } 31 32 public static class BuszThread implements Runnable { 33 34 private String name; 35 private Object take; 36 private Object waitFor; 37 public BuszThread(String name, Object take, Object waitFor){ 38 this.name = name; 39 this.take = take; 40 this.waitFor = waitFor; 41 } 42 @Override 43 public void run() { 44 System.out.println(name + " 开始执行"); 45 46 while (true) { 47 synchronized (waitFor) { 48 try { 49 System.out.println(name + " 开始等待它需要的条件"); 50 waitFor.wait(); 51 System.out.println(name + " 获得了它需要的等待条件"); 52 Thread.sleep(1000); 53 System.out.println(name + " 执行完成,并释放它持有的等待条件"); 54 } catch (InterruptedException e) { 55 e.printStackTrace(); 56 } 57 } 58 59 synchronized (take){ 60 take.notify(); 61 } 62 } 63 64 } 65 } 66 }
2使用lock中的Condition
1 package com.nmcc.thread; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 import java.util.concurrent.atomic.AtomicBoolean; 6 import java.util.concurrent.locks.Condition; 7 import java.util.concurrent.locks.Lock; 8 import java.util.concurrent.locks.ReentrantLock; 9 10 /** 11 * TODO 12 * 13 * @author nmcc 14 * @version V1.0 15 * @date 2021-08-24 08:49 16 * 17 */ 18 public class SyncRun { 19 private static Lock lock = new ReentrantLock(false); 20 private static Condition a_c = lock.newCondition(); 21 private static Condition b_c = lock.newCondition(); 22 private static Condition c_c = lock.newCondition(); 23 24 public static void main(String[] args) throws InterruptedException { 25 ExecutorService executor = Executors.newFixedThreadPool(3); 26 executor.execute(new BuszThread("C", c_c, b_c, false)); 27 executor.execute(new BuszThread("B", b_c, a_c, false)); 28 executor.execute(new BuszThread("A", a_c, c_c, false)); 29 Thread.sleep(1000); 30 lock.lock(); 31 try { 32 c_c.signal(); 33 } finally { 34 lock.unlock(); 35 } 36 37 38 } 39 40 public static class BuszThread implements Runnable { 41 42 private String name; 43 private Condition take; 44 private Condition waitFor;47 public BuszThread(String name, Condition take, Condition waitFor){ 48 this.name = name; 49 this.take = take; 50 this.waitFor = waitFor;52 } 53 @Override 54 public void run() { 55 System.out.println(name + " 开始执行"); 56 while (true){ 57 lock.lock(); 58 try { 59 System.out.println(name + " 开始等待它需要的条件"); 60 waitFor.await(); 61 System.out.println(name + " 获得了它需要的等待条件"); 62 Thread.sleep(1000); 63 System.out.println(name + " 执行完成,并释放它持有的等待条件"); 64 take.signal(); 65 66 } catch (InterruptedException e) { 67 e.printStackTrace(); 68 }finally { 69 lock.unlock(); 70 } 71 } 72 } 73 } 74 }
这两种方式,首先都需要获取到锁,然后等待他需要的前置条件,前置条件执行后,轮到他执行,然后它再去释放他持有的前置条件,
Condition是一个lock实例出来的,他们获取的都市一个lock的锁,而如果要调用object的wait和notify方法,首先要获取对应的object的锁。
3使用原子变量,这种方式其实不是线程间通信,他是用原子变量的比较并替换原子,让两个线程去交替的替换成功。
package com.nmcc.thread; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** * 两个线程交替打印奇偶数 * * @author nmcc * @version V1.0 * @date 2021-09-02 16:53 */ public class SyncPrint { private static AtomicInteger num = new AtomicInteger(0); public static void main(String[] args) { ThreadPoolExecutor executor = new ThreadPoolExecutor(2,2,60, TimeUnit.SECONDS,new LinkedBlockingQueue<>()); executor.execute(new Printer(num, 0, "A")); executor.execute(new Printer(num, 1, "B")); } public static class Printer implements Runnable{ private AtomicInteger num; private Integer start; private Integer step = 1; private String name; public Printer(AtomicInteger num, Integer start, String name) { this.num = num; this.start = start; this.name = name; } @Override public void run() { try { while (true){ Integer update = start + step; Thread.sleep(1000); if (num.compareAndSet(start, update)){ System.out.println(name + " say: " + update); start +=2; Thread.sleep(1000); } } } catch (InterruptedException e) { e.printStackTrace(); } } } }