zoukankan      html  css  js  c++  java
  • 多线程案例

    一、线程的交替打印问题

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

      

  • 相关阅读:
    使用Visual Studio 2010来部署Windows应用程序
    如何显示一个非激活窗体
    构建ASP.NET网站十大必备工具(2)
    在Azure中创建一个“Hello World”应用程序
    轻松搞定VS2010 和旧版本服务器一起使用的问题
    Sql注入与转义
    小数型 Float(M,D),decimal(M,D)
    MySQL SQL语句
    作业综合练习配置+自定义函数设置
    作业综合练习初始化工作
  • 原文地址:https://www.cnblogs.com/helloworldcode/p/13450812.html
Copyright © 2011-2022 走看看