一、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();
}
}