美文网首页
多线程顺序处理的方式

多线程顺序处理的方式

作者: 名字是乱打的 | 来源:发表于2021-09-07 23:17 被阅读0次

    目前有个任务需要对数据进行一个循环处理,那么就需要多线程顺序触发的问题了.
    这里以顺序打印为例子对常见的多线程顺序处理做个总结,拿出两个非常常用的方式.

    方法一: 资源+锁

    核心点:
    1.锁共同资源lock
    2.通过while循环判断每次被唤醒是否要再次阻塞

    public class ThreadsPrintOrder {
        private static Integer curr = 0;
        private static String[] strs = new String[]{"A", "B", "C"};
        private static int count = 10;
        static  Object lock=new Object();
    
        public static void main(String[] args) {
            final Thread a = getThread("A");
            final Thread b = getThread("B");
            final Thread c = getThread("C");
    
            a.start();
            b.start();
            c.start();
        }
    
        private static Thread getThread(String threadName) {
            return new Thread(() -> {
                synchronized (lock) {
                    for (int i = 0; i < count; i++) {
                        while (!strs[curr%strs.length].equals(threadName)) {
                            try {
                                lock.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println(Thread.currentThread().getName());
                        curr++;
                        lock.notifyAll();
                    }
                }
            }, threadName);
        }
    }
    

    方法二 一个ReentrantLock加多个conditon实现(推荐,安全性,性能和可读性较高)

    上面那种方法有个缺点就是每个线程被唤醒是随机的,每次被唤醒的可能是我们不想打印的线程,需要它再次自我关闭.
    而ReentrantLock的独特效果可以做到结合conditon实现定向唤醒.

    public class ThreadsPrintOrder_m2 {
        static int count=10;
        public static void main(String[] args) {
            LockOrderPrint lockOrder=new LockOrderPrint();
            new Thread(()->{
                for (int i = 0; i <count ; i++) {
                    lockOrder.printA();
                }
            }).start();
    
            new Thread(()->{
                for (int i = 0; i <count ; i++) {
                    lockOrder.printB();
                }
            }).start();
    
            new Thread(()->{
                for (int i = 0; i <count ; i++) {
                    lockOrder.printC();
                }
            }).start();
        }
    }
    
    class LockOrderPrint {
        int flag=0;
        Lock lock=new ReentrantLock();
        Condition conditionA=lock.newCondition();
        Condition conditionB=lock.newCondition();
        Condition conditionC=lock.newCondition();
    
        public void printA(){
            lock.lock();
            try {
                while (flag%3!=0){
                    try {
                        conditionA.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("A");
                flag++;
                conditionB.signal();
    
            }catch (Exception exce){
                exce.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    
        public void printB(){
            lock.lock();
            try {
                while (flag%3!=1){
                    try {
                        conditionB.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("B");
                flag++;
                conditionC.signal();
            }catch (Exception exce){
                exce.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    
        public void printC(){
            lock.lock();
            try {
                while (flag%3!=2){
                    try {
                        conditionC.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("C");
                flag++;
                conditionA.signal();
            }catch (Exception exce){
                exce.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    
    }
    
    

    方法三 基于信号量来做

    public class ThreeThreadPrintOrder {
        static AtomicInteger flag = new AtomicInteger();
    
        //打印次数
        public static void main(String[] args) throws InterruptedException {
            Semaphore semaphore = new Semaphore(1);
    
            new Thread(() -> {
                while (true) {
                    try {
                        semaphore.acquire();
                        if (flag.get() % 3 == 0) {
                            System.out.println(Thread.currentThread().getName());
                            flag.incrementAndGet();
                        }
                        semaphore.release();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }, "A").start();
    
    
            new Thread(() -> {
                while (true) {
                    try {
                        semaphore.acquire();
                        if (flag.get() % 3 == 1) {
                            System.out.println(Thread.currentThread().getName());
                            flag.incrementAndGet();
                        }
                        semaphore.release();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "B").start();
    
            new Thread(() -> {
                while (true) {
                    try {
                        semaphore.acquire();
                        if (flag.get() % 3 == 2) {
                            System.out.println(Thread.currentThread().getName());
                            flag.incrementAndGet();
                        }
                        semaphore.release();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "C").start();
    
    
            Thread.currentThread().wait();
    
        }
    }
    
    

    相关文章

      网友评论

          本文标题:多线程顺序处理的方式

          本文链接:https://www.haomeiwen.com/subject/gvjmwltx.html