并行设计模式

524 阅读2分钟

信号量模式

实现任务间相互通信,采用信号量或者互斥实现:Semaphore、ReebtrantLock、wait()notify()

下例使用 wait() notify() 实现

package ThreadFrame.并行模式;
/**
 * @author mojiayi
 * @date 2019-02-09 13:54
 */
public class FrameDemo implements Runnable {
    private int flag;
    private Object object;
    FrameDemo(
            Object o
    ){
        this.object = o;
    }
    public static void test(int i){
        System.out.println(Thread.currentThread().getName()+" "+i);
    }

    public void task1(){
        synchronized (object) {
            test(1);
            object.notify();
        }
    }

    public void task2() throws InterruptedException {
        synchronized (object) {
            object.wait();
            test(2);
            object.notify();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Object o = new Object();
        FrameDemo demo1 = new FrameDemo(o);
        FrameDemo demo2 = new FrameDemo(o);
        demo1.flag = 1;
        new Thread(demo2).start();
        Thread.sleep(1000);
        new Thread(demo1).start();
    }

    @Override
    public void run() {
        if(flag == 1)
            task1();
        else {
            try {
                task2();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

会和模式

此模式是信号模式的扩展,当第一个任务在等待第二个任务的某一事件,而第二哥任务又在等待第一个任务的某一事件时:
public void task1() throws InterruptedException {
        synchronized (object) {
            test(1);
            object.notify();
            object.wait();
            object.notify();
            test(3);
        }
}

public void task2() throws InterruptedException {
    synchronized (object) {
        test(2);
        object.notify();
        object.wait();
        object.notify();
        test(4);
    }
}

临界模式

此模式用于设置某一临界段来限制执行线程,就是我们所说的同步。

多元复用模式

这是临界模式的扩展,在临界模式的基础上限制执行临界段的线程数量,一般用 Semaphore 类实现。
package ThreadFrame.并行模式;

import java.util.concurrent.Semaphore;

/**
 * @author mojiayi
 * @date 2019-02-09 13:54
 */
public class FrameDemo implements Runnable {
    private int flag;
    private static int i;
    Semaphore c;
    Semaphore p;
    Semaphore m;

    public FrameDemo(int flag, Semaphore c,Semaphore p, Semaphore m) {
        this.flag = flag;
        this.c = c;
        this.p = p;
        this.m = m;
    }

    public void consume() throws InterruptedException {
        m.acquire();
        //System.out.println("2");
        if (c.availablePermits() <= 0){
            m.release();
            return;
        }
        c.acquire();
        i = i - 1;
        System.out.println("c: "+p.availablePermits()+" "+c.availablePermits()+" "+m.availablePermits()+" "+i);
        if(i<0)
            System.exit(0);
        p.release();
        m.release();
    }

    public void produce() throws InterruptedException {
        m.acquire();
        //System.out.println("1");
        if(p.availablePermits()<=0) {
            m.release();
            return;
        }
        p.acquire();
        i = i + 1;
        System.out.println("p "+p.availablePermits()+" "+c.availablePermits()+" "+m.availablePermits()+" "+i);
        if(i>10)
            System.exit(0);
        c.release();
        m.release();
    }

    @Override
    public void run() {
        if(flag == 1) {
            try {
                while(true)
                    produce();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        else {
            try {
                while (true)
                    consume();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(0);
        Semaphore semaphore1 = new Semaphore(10);
        Semaphore semaphore2 = new Semaphore(1);
        for(int i = 0; i < 3; i++) {
            FrameDemo f1 = new FrameDemo(1, semaphore, semaphore1, semaphore2);
            Thread thread = new Thread(f1);
            thread.setName("producer "+i);
            thread.start();
        }
        for(int i = 0; i < 3; i++) {
            FrameDemo f2 = new FrameDemo(0, semaphore, semaphore1, semaphore2);
            Thread thread = new Thread(f2);
            thread.setName("consumer "+i);
            thread.start();
        }
    }
}

多生产多消费,生产最大值为10,生产消费线程各三个。

栅栏模式

在某一点上实现任务同步,只有所有任务都到达同步点后才能继续运行,一般借助CyclicBarrier类实现。
package ThreadFrame.并行模式;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * @author mojiayi
 * @date 2019-02-12 00:05
 */
public class ThreadDemo2 {
        final int N;
        final float[][] data;
        final CyclicBarrier barrier;

        class Worker implements Runnable {
            int myRow;
            Worker(int row) { myRow = row; }
            public void run() {
                int sum = 0;
                for(int i = 0; i < data[myRow].length; i++){
                    sum += data[myRow][i];
                }
                System.out.println(barrier.isBroken());
                System.out.println(Thread.currentThread().getName() + " " + sum);
                    try {
                        barrier.await();
                    } catch (InterruptedException ex) {
                        return;
                    } catch (BrokenBarrierException ex) {
                        return;
                    }
            }
        }

        public ThreadDemo2(float[][] matrix) {
            data = matrix;
            N = matrix.length;
            //初始化CyclicBarrier
            barrier = new CyclicBarrier(N, new Runnable() {
                public void run() {
                    System.out.println("end"); //合并行
                }
            });
            for (int i = 0; i < N; ++i)
                new Thread(new Worker(i)).start();
        }

    public static void main(String[] args) {
        float[][] floats = {{1,2,3},{2,3,4},{4,5,6}};
        ThreadDemo2 demo2 = new ThreadDemo2(floats);
    }
}