一、生产者消费者案例
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 }