一、生产者消费者案例
1.使用synchronized关键字实现
1 public class TestProductorAndConsumer { 2 public static void main(String[] args) { 3 Clerk clerk = new Clerk(); 4 Productor pro = new Productor(clerk); 5 Consumer cus = new Consumer(clerk); 6 7 new Thread(pro, "生产者 A").start(); 8 new Thread(cus, "消费者 B").start(); 9 new Thread(pro, "生产者 C").start(); 10 new Thread(cus, "消费者 D").start(); 11 } 12 } 13 //店员 14 class Clerk{ 15 private int product = 0; 16 //进货 17 public synchronized void get(){ //循环次数:0 18 while(product >= 1){ 19 System.out.println("产品已满!"); 20 try { 21 this.wait(); //为了避免虚假唤醒问题,wait应该总是使用在循环中 22 } catch (InterruptedException e) { 23 } 24 } 25 System.out.println(Thread.currentThread().getName() + " : " + ++product); 26 this.notifyAll(); 27 } 28 //卖货 29 public synchronized void sale(){ //product = 0; 循环次数:0 30 while(product <= 0){ 31 System.out.println("缺货!"); 32 try { 33 this.wait(); 34 } catch (InterruptedException e) { 35 } 36 } 37 System.out.println(Thread.currentThread().getName() + " : " + --product); 38 this.notifyAll(); 39 } 40 } 41 //生产者 42 class Productor implements Runnable{ 43 private Clerk clerk; 44 public Productor(Clerk clerk) { 45 this.clerk = clerk; 46 } 47 public void run() { 48 for (int i = 0; i < 20; i++) { 49 try { 50 Thread.sleep(200); 51 } catch (InterruptedException e) { 52 } 53 clerk.get(); 54 } 55 } 56 } 57 //消费者 58 class Consumer implements Runnable{ 59 private Clerk clerk; 60 public Consumer(Clerk clerk) { 61 this.clerk = clerk; 62 } 63 public void run() { 64 for (int i = 0; i < 20; i++) { 65 clerk.sale(); 66 } 67 } 68 }
2.使用Lock同步锁和Condition类实现
1 public class TestProductorAndConsumerForLock { 2 public static void main(String[] args) { 3 Clerk clerk = new Clerk(); 4 Productor pro = new Productor(clerk); 5 Consumer con = new Consumer(clerk); 6 7 new Thread(pro, "生产者 A").start(); 8 new Thread(con, "消费者 B").start(); 9 // new Thread(pro, "生产者 C").start(); 10 // new Thread(con, "消费者 D").start(); 11 } 12 } 13 class Clerk { 14 private int product = 0; 15 private Lock lock = new ReentrantLock(); 16 private Condition condition = lock.newCondition(); 17 // 进货 18 public void get() { 19 lock.lock(); 20 try { 21 if (product >= 1) { // 为了避免虚假唤醒,应该总是使用在循环中。 22 System.out.println("产品已满!"); 23 try { 24 condition.await(); 25 } catch (InterruptedException e) { 26 } 27 } 28 System.out.println(Thread.currentThread().getName() + " : "+ ++product); 29 condition.signalAll(); 30 } finally { 31 lock.unlock(); 32 } 33 } 34 // 卖货 35 public void sale() { 36 lock.lock(); 37 try { 38 if (product <= 0) { 39 System.out.println("缺货!"); 40 try { 41 condition.await(); 42 } catch (InterruptedException e) { 43 } 44 } 45 System.out.println(Thread.currentThread().getName() + " : "+ --product); 46 condition.signalAll(); 47 } finally { 48 lock.unlock(); 49 } 50 } 51 } 52 53 // 生产者 54 class Productor implements Runnable { 55 private Clerk clerk; 56 public Productor(Clerk clerk) { 57 this.clerk = clerk; 58 } 59 public void run() { 60 for (int i = 0; i < 20; i++) { 61 try { 62 Thread.sleep(200); 63 } catch (InterruptedException e) { 64 e.printStackTrace(); 65 } 66 clerk.get(); 67 } 68 } 69 } 70 71 // 消费者 72 class Consumer implements Runnable { 73 private Clerk clerk; 74 public Consumer(Clerk clerk) { 75 this.clerk = clerk; 76 } 77 public void run() { 78 for (int i = 0; i < 20; i++) { 79 clerk.sale(); 80 } 81 } 82 }
二、线程按序交替
编写一个程序,开启3个线程,这三个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出的结果必须按顺序显示。如:ABCABC......依次递归。
1 public class TestABCAlternate { 2 public static void main(String[] args) { 3 AlternateDemo ad = new AlternateDemo(); 4 new Thread(new Runnable() { 5 public void run() { 6 for (int i = 1; i <= 10; i++) { 7 ad.loopA(i); 8 } 9 } 10 }, "A").start(); 11 new Thread(new Runnable() { 12 public void run() { 13 for (int i = 1; i <= 10; i++) { 14 ad.loopB(i); 15 } 16 } 17 }, "B").start(); 18 new Thread(new Runnable() { 19 public void run() { 20 for (int i = 1; i <= 10; i++) { 21 ad.loopC(i); 22 System.out.println("-----------------------------------"); 23 } 24 } 25 }, "C").start(); 26 } 27 } 28 29 class AlternateDemo{ 30 private int number = 1; //当前正在执行线程的标记 31 private Lock lock = new ReentrantLock(); 32 private Condition condition1 = lock.newCondition(); 33 private Condition condition2 = lock.newCondition(); 34 private Condition condition3 = lock.newCondition(); 35 36 public void loopA(int totalLoop){ //totalLoop : 循环第几轮 37 lock.lock(); 38 try { 39 if(number != 1){ //1. 判断 40 condition1.await(); 41 } 42 //2. 打印 43 for (int i = 1; i <= 1; i++) { 44 System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop); 45 } 46 //3. 唤醒 47 number = 2; 48 condition2.signal(); 49 } catch (Exception e) { 50 e.printStackTrace(); 51 } finally { 52 lock.unlock(); 53 } 54 } 55 public void loopB(int totalLoop){ 56 lock.lock(); 57 try { 58 if(number != 2){ //1. 判断 59 condition2.await(); 60 } 61 //2. 打印 62 for (int i = 1; i <= 1; i++) { 63 System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop); 64 } 65 //3. 唤醒 66 number = 3; 67 condition3.signal(); 68 } catch (Exception e) { 69 e.printStackTrace(); 70 } finally { 71 lock.unlock(); 72 } 73 } 74 public void loopC(int totalLoop){ 75 lock.lock(); 76 try { 77 if(number != 3){ //1. 判断 78 condition3.await(); 79 } 80 //2. 打印 81 for (int i = 1; i <= 1; i++) { 82 System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop); 83 } 84 //3. 唤醒 85 number = 1; 86 condition1.signal(); 87 } catch (Exception e) { 88 e.printStackTrace(); 89 } finally { 90 lock.unlock(); 91 } 92 } 93 }