java实现交替打印的四种方法

交替打印就是要实现线程间通信,有两种方式:

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();
           }
       }
   }
}

4使用阻塞队列

 1 package com.nmcc.thread;
 2 
 3 import java.util.concurrent.ExecutorService;
 4 import java.util.concurrent.Executors;
 5 import java.util.concurrent.LinkedBlockingQueue;
 6 
 7 /**
 8  * TODO
 9  *
10  * @author nmcc
11  * @version V1.0
12  * @date 2021-08-24 08:49
13  *
14  */
15 public class SyncRunThree {
16 
17     public static LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>(1);
18     public static void main(String[] args) throws InterruptedException {
19         ExecutorService executor = Executors.newFixedThreadPool(3);
20         executor.execute(new BuszThread("C", queue));
21         executor.execute(new BuszThread("B", queue));
22         executor.execute(new BuszThread("A", queue));
23         Thread.sleep(1000);
24         queue.put(1);
25     }
26 
27     public static class BuszThread implements Runnable {
28 
29         private String name;
30         private LinkedBlockingQueue<Integer> queue;
31         public BuszThread(String name, LinkedBlockingQueue<Integer> queue){
32             this.name = name;
33             this.queue = queue;
34         }
35         @Override
36         public void run() {
37             System.out.println(name + " 开始执行");
38 
39                 while (true) {
40                     try {
41                         System.out.println(name + " 准备获取");
42                         Integer num = queue.take();
43                         System.out.println(name + " 获取到:" + num);
44                         queue.put(++num);
45                         Thread.sleep(1000);
46                     } catch (InterruptedException e) {
47                         e.printStackTrace();
48                     }
49                 }
50             }
51 
52     }
53 }
原文地址:https://www.cnblogs.com/nmcc33/p/15221893.html