多线程案例
一、线程的交替打印问题
两个线程交替打印字母和数字,其中线程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();
}
}
}
}
很希望自己是一棵树,守静、向光、安然,敏感的神经末梢,触着流云和微风,窃窃的欢喜。脚下踩着最卑贱的泥,很踏实。还有,每一天都在隐秘成长。

浙公网安备 33010602011771号