有三个线程怎么保证顺序性

保证顺序性其实就是java多线程通信的问题。三个线程协定执行的先后顺序,转换成线程通信的问题,我需要用一个东西来协定执行到哪个线程了,这东西实现方式就有很多了:

Java的线程通信都是使用内存共享变量的方式,那么就简单的方式就是:

  1. 一个共享变量。这个共享变量可以是一个简单的静态变量,可以是一个Semaphore等。

其实如果考虑抢锁会消耗性能,如果我不跑的线程进行挂起呢?

实现方式2

2)线程的wait和notify

如果对底层了解一点,我个人理解性能最高的方式其实是直接使用LockSupport.park()

实现方式3:

LockSupport.park()

我们把这个题目具体化点:

三个线程,A线程打印A,B线程打印B,C线程打印C,按顺序依次打印10_0000次,输出ABCABCABCABCABCABCABCABCABCABC……。

下面是我实现的代码,除了实现功能之外,我还想证明下自己的想法:实现方式3是最优的方案。

第一种方式:

public class PrintAbc {
    private int n;
    private static long statTime;

    private Semaphore aSemaphore = new Semaphore(1);
    private Semaphore bSemaphore = new Semaphore(0);
    private Semaphore cSemaphore = new Semaphore(0);

    static Thread threadA = null;
    static Thread threadB = null;
    static Thread threadC = null;

    public void printA() throws InterruptedException {

        for (int i = 0; i < n; i++) {
            aSemaphore.acquire();
            System.out.print("A");
            bSemaphore.release();
        }
    }

    public void printB() throws InterruptedException {

        for (int i = 0; i < n; i++) {
            bSemaphore.acquire();
            System.out.print("B");
            cSemaphore.release();
        }
        System.out.println("elapse time: "+(System.currentTimeMillis() - statTime));
    }
    public void printC() throws InterruptedException {

        for (int i = 0; i < n; i++) {
            cSemaphore.acquire();
            System.out.print("C");
            aSemaphore.release();
        }
    }

    public static void main(String[] args) {
        PrintAbc printAbc = new PrintAbc(10_0000);
        Runnable printA = () -> {
            try {
                printAbc.printA();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Runnable printB = () -> {
            try {
                printAbc.printB();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Runnable printC = () -> {
            try {
                printAbc.printC();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        threadA = new Thread(printA);
        threadB = new Thread(printB);
        threadC = new Thread(printC);
        statTime = System.currentTimeMillis();
        threadA.start();
        threadB.start();
        threadC.start();
    }

}

最终平均消耗的时间是:

elapse time: 2282

第二种方式感兴趣的童鞋自己实现下,但是理论上性能不会高到哪去。

第三种实现:

public class PrintAbc {

    private int n;
    private static long statTime;

    public PrintAbc(int n) {
        this.n = n;
    }

    static Thread threadA = null;
    static Thread threadB = null;
    static Thread threadC = null;

    public void printA() throws InterruptedException {

        for (int i = 0; i < n; i++) {
            LockSupport.park(threadA);
            System.out.print("A");
            LockSupport.unpark(threadB);
        }
    }

    public void printB() throws InterruptedException {

        for (int i = 0; i < n; i++) {
            LockSupport.park(threadB);
            System.out.print("B");
            LockSupport.unpark(threadC);
        }
        System.out.println("elapse time: "+(System.currentTimeMillis() - statTime));
    }
    public void printC() throws InterruptedException {

        for (int i = 0; i < n; i++) {
        	LockSupport.park(threadC);
            System.out.print("C");
            LockSupport.unpark(threadA);
        }
    }

    public static void main(String[] args) {
        PrintAbc printAbc = new PrintAbc(10_0000);
        Runnable printA = () -> {
            try {
                printAbc.printA();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Runnable printB = () -> {
            try {
                printAbc.printB();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Runnable printC = () -> {
            try {
                printAbc.printC();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        threadA = new Thread(printA);
        threadB = new Thread(printB);
        threadC = new Thread(printC);
        statTime = System.currentTimeMillis();
        threadA.start();
        threadB.start();
        threadC.start();

        LockSupport.unpark(threadA);
    }
}

最终平均消耗时间为:

elapse time: 1948

而且测试的过程中,有的时候LockSupport的方式耗时比aSemaphore,应该是上下文交互太厉害了,如果读者有更好的方式,欢迎告诉我,给我留言。大家互相学习,非常感谢。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值