多线程案例
一、线程的交替打印问题
两个线程交替打印字母和数字,其中线程1打印数字,线程2打印字母,打印形式如下:
12A34B56C......
方法一,使用ReentrantLock实现,程序如下:
public class ThreadTest02 { private static Lock lock = new ReentrantLock(); private static Condition conditionA = lock.newCondition(); private static Condition conditionB = lock.newCondition(); private static volatile boolean flag = true; public void printNum(int i) throws InterruptedException { lock.lock(); while (!flag){ conditionA.await(); } System.out.print(2 * i - 1); System.out.print(2 * i); flag = false; conditionB.signal(); lock.unlock(); } public void printChar(int i) throws InterruptedException { lock.lock(); while (flag){ conditionB.await(); } System.out.print(Character.toChars(i - 1 + 'A')); flag = true; conditionA.signal(); lock.unlock(); } public static void main(String[] args) { ThreadTest02 test02 = new ThreadTest02(); new Thread(new Runnable() { @Override public void run() { for (int i = 1; i < 27; i++) { try { test02.printNum(i); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { for (int i = 1; i < 27; i++) { try { test02.printChar(i); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } }
condition也是基于AQS实现的,内部维护了一个 等待队列,所有调用condition.await方法的线程会加入到等待队列中,并且线程状态转换为等待状态。当调用condition.await()方法后会使得当前获取lock的线程进入到等待队列,如果该线程能够从await()方法返回的话一定是该线程获取了与condition相关联的lock。
方法二,使用synchronized关键字解决:
public class ThreadTest03 { private static Object object = new Object(); private static volatile boolean flag = true; public void printNum(int i) throws InterruptedException { synchronized (object){ if(!flag){ object.wait(); } System.out.print(i * 2 - 1); System.out.print(i * 2); flag = false; object.notify(); } } public void printChar(int i) throws InterruptedException { synchronized (object){ if(flag){ object.wait(); } System.out.print(Character.toChars(i - 1 + 'A')); flag = true; object.notify(); } } public static void main(String[] args) { ThreadTest03 test03 = new ThreadTest03(); new Thread(new Runnable() { @Override public void run() { for (int i = 1; i < 27; i++) { try { test03.printNum(i); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { for (int i = 1; i < 27; i++) { try { test03.printChar(i); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } }
二、生产者和消费者问题
生产者-消费者问题,实际上是指程序中包含两类线程,一种是用于生产数据的生产者线程,另一种是用于消费数据的消费者线程,生产者生产的数据放置于一个有固定容量的缓冲区当中,消费者从这个缓冲区中拿出数据消费。主要解决两个问题:
- 如果共享数据区已满的话,阻塞生产者继续生产数据放置入内;
- 如果共享数据区为空的话,阻塞消费者继续消费数据;
代码如下:
package com.practice.threadDemo; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class PSThreadTest04 { private static Lock lock = new ReentrantLock(); private static Condition conditionA = lock.newCondition(); private static Condition conditionB = lock.newCondition(); private static volatile int free_size = 10; //缓冲区可以容纳的大小 public static void main(String[] args) { PSThreadTest04 test04 = new PSThreadTest04(); for (int k = 0; k < 5; k++) { new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 3; i++) { try { test04.new Producer().produce(); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } for (int k = 0; k < 5; k++) { new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 3; i++) { try { test04.new Consumer().consume(); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } } /**方法一 :ReentrantLock的方式实现 **/ class Producer { public void produce() throws InterruptedException { lock.lock(); while (free_size <= 0) { conditionA.await(); } System.out.println("生产者生产了一件产品"); free_size--; conditionB.signal(); lock.unlock(); } } class Consumer { public void consume() throws InterruptedException { lock.lock(); while (free_size == 10) { conditionB.await(); } System.out.println("消费者消费了一件产品"); free_size++; conditionA.signal(); lock.unlock(); } } }
此处也提供了第二种方法去实现:
package com.practice.threadDemo; public class PSThreadTest04 { private static volatile int free_size = 10; //缓冲区可以容纳的大小 private static volatile Object object = new Object(); public static void main(String[] args) { PSThreadTest04 test04 = new PSThreadTest04(); for (int k = 0; k < 5; k++) { new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 3; i++) { try { test04.new Producer().produce(); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } for (int k = 0; k < 5; k++) { new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 3; i++) { try { test04.new Consumer().consume(); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } } /**方法二 :synchronized的方式实现 **/ class Producer{ public void produce() throws InterruptedException { synchronized (object){ while(free_size <= 0){ object.wait(); } System.out.println("生产者生产了一件产品"); free_size--; object.notify(); } } } class Consumer{ public void consume() throws InterruptedException { synchronized (object){ while(free_size >= 10){ object.wait(); } System.out.println("消费者消费了一件产品"); free_size++; object.notify(); } } } }
很希望自己是一棵树,守静、向光、安然,敏感的神经末梢,触着流云和微风,窃窃的欢喜。脚下踩着最卑贱的泥,很踏实。还有,每一天都在隐秘成长。