多线程——Semaphore

6 篇文章 0 订阅
5 篇文章 0 订阅

一、Semaphore的作用

Semaphore是控制线程并发数量的,可以通过Semaphore来控制线程的执行顺序与逻辑

简单介绍一下怎么使用

//参数为 1 代表 s1 有 1块钱 ,就和超市使用购物车一样,要插入一元硬币才能使用
//acquire()这句话就代表你把这一块钱租购物车,release()这句话是相反的,是把一块钱拿回来的
Semaphore s1 = new Semaphore(1);

//这里参数为 0 ,代表你没有钱,就得等别人把 1 块钱给你
Semaphore s2 = new Semaphore(0);

二、我们通过三道多线程题来理解一下

1》两个线程交替打印1—100的数字

import java.util.concurrent.Semaphore;

/**
 * 两个线程交替打印1—100的数字
 */
public class Thread_1 {

    public static volatile int i = 1;

    public static void main(String[] args) {
        //这里我们先从线程1开始,所以给s1参数为1,代表有1块钱
        Semaphore s1 = new Semaphore(1); 
        //而线程2需要等待线程1结束,将1块钱释放给s2,形成一个循环
        Semaphore s2 = new Semaphore(0);
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (i <= 100) {
                    try {
                        s1.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (i <= 100) {
                        System.out.println(Thread.currentThread().getName() + " " + i++);
                    }
                    //把钱给s2
                    s2.release();

                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (i <= 100) {
                    try {
                        s2.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (i <= 100) {
                        System.out.println(Thread.currentThread().getName() + " " + i++);
                    }
                    //把钱给s1
                    s1.release();
                }
            }
        }).start();
    }
}

 运行结果图

 

2》三个线程打印,2线程打印3的倍数,3线程打印5的倍数,1线程打印剩下的数字,1~100以内

这次代码,我们可以组织一下逻辑

  •  从数字1开始,我们先给线程1的Semaphore赋初值为1,其余的设置为0;
  • 线程1执行完,进行判断,下一个数字(2)是否是自己的打印对象,是,就把线程1的Semaphore在给线程1,如果是3或者5的倍数 就把Semaphore给线程2;
  • 线程2拿到Semaphore在进行判断,i 到底是3的倍数还是5的倍数,3的倍数继续打印,是5的倍数则传给线程3,其余的传回线程1;
  • 线程3拿到Semaphore和线程2的逻辑思考差不多;
/**
 * 三个线程打印,2线程打印3的倍数,3线程打印5的倍数,1线程打印剩下的数字,1~100以内
 */

import java.util.concurrent.Semaphore;

public class Thread_2 {
    public static volatile int i = 1;

    public static void main(String[] args) {
        Semaphore s1 = new Semaphore(1);
        Semaphore s2 = new Semaphore(0);
        Semaphore s3 = new Semaphore(0);
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (i <= 100) {
                    try {
                        s1.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (i % 3 != 0 && i % 5 != 0 && i <= 100) {
                        System.out.println(Thread.currentThread().getName() + " " + i++);
                    }
                    if (i % 3 == 0 || i % 5 == 0) {
                        s2.release();
                    } else {
                        s1.release();
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (i <= 100) {
                    try {
                        s2.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (i % 3 == 0 && i <= 100) {
                        System.out.println(Thread.currentThread().getName() + " " + i++);
                    }
                    if (i % 3 != 0 && i % 5 != 0) {
                        s1.release();
                    } else {
                        s3.release();
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (i <= 100) {
                    try {
                        s3.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (i % 5 == 0 && i <= 100) {
                        System.out.println(Thread.currentThread().getName() + " " + i++);
                    }
                    if (i % 3 != 0) {
                        s1.release();
                    } else {
                        s2.release();
                    }
                }
            }
        }).start();

    }
}

结果

3》开两个线程,交替打印两个长度不同的数组

static int[] num1 = {1, 3, 5, 7, 9};
static int[] num2 = {2, 4, 6, 8, 10, 11, 12};

这个可以先不看代码,可以自己实现一下,结果如下

 











/**
 * 开两个线程,交替打印两个长度不同的数组
 */
import java.util.concurrent.Semaphore;

public class Thread_3 {
    static int[] num1 = {1, 3, 5, 7, 9};
    static int[] num2 = {2, 4, 6, 8, 10, 11, 12};
    static volatile int i = 0;
    static volatile int j = 0;

    public static void main(String[] args) {
        Semaphore s1 = new Semaphore(1);
        Semaphore s2 = new Semaphore(0);
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (i < num1.length) {
                    try {
                        s1.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " " + num1[i++]);
                    if (j >= num2.length) {
                        s1.release();
                    } else {
                        s2.release();
                    }
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (j < num2.length) {
                    try {
                        s2.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " " + num2[j++]);
                    if (i >= num1.length) {
                        s2.release();
                    }else {
                        s1.release();
                    }
                }
            }
        }).start();
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值