多线程案例

一、线程的交替打印问题

  两个线程交替打印字母和数字,其中线程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();
    }
}

二、生产者和消费者问题

  生产者-消费者问题,实际上是指程序中包含两类线程,一种是用于生产数据的生产者线程,另一种是用于消费数据的消费者线程,生产者生产的数据放置于一个有固定容量的缓冲区当中,消费者从这个缓冲区中拿出数据消费。主要解决两个问题:

  1. 如果共享数据区已满的话,阻塞生产者继续生产数据放置入内;
  2. 如果共享数据区为空的话,阻塞消费者继续消费数据;

代码如下:

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

  

posted @ 2020-08-07 09:41  晓乎  阅读(374)  评论(0编辑  收藏  举报
总访问: counter for blog 次