您的位置:首页 > 编程语言 > Java开发

java并行计算--Semaphore信号量的简单使用

2017-03-29 22:00 489 查看
多线程不仅适用于IO密集型任务,而且在计算型密集型任务也是同样很有优势,最直观的就是快嘛!先来假设一个任务场景:

假设场景:

有一个计算任务:需要先计算出A,B的结果,通过A,B结果得到C结果,通过A,B,C结果得到结果D,试用多线程完成任务!!

分析

我们知道线程的执行顺序具有不可预测性,那么直接使用4个线程去跑,那么由于执行顺序就会无法预测,结果的正确性就得不到保证,如何控制线程的执行顺序就成为最主要的解决问题。这里我们就需要使用Semaphore这个类库了。我们来看jdk文档的介绍:

一个计数信号量。从概念上讲,信号量维护了一个许可集。
如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。
每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。
但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。
Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目


我们通过这种信号量的阻塞方式来实现线程的执行方式,通过 acquire()阻塞, release() 来释放阻塞。来看一段小程序:

package cacl;

import java.util.concurrent.*;

/**
* Created by lewis on 2017/3/28.
*
*
*/
public class Cacl {

private static volatile Semaphore a,b,c,d;

static {
a = new Semaphore(0);
b = new Semaphore(0);
c = new Semaphore(0);
d = new Semaphore(0);
}

public static void main(String []args){
Thread t1 = new Thread(new A());
Thread t2 = new Thread(new B());
Thread t3 = new Thread(new C());
Thread t4 = new Thread(new D());
t1.start();
t2.start();
t3.start();
t4.start();
}
public static <T> void print(T s){
System.out.println(s);
}

static class  A implements Runnable{
@Override
public void run() {
print("A");
a.release();
}
}

static class  B implements Runnable{
@Override
public void run() {
print("B");
b.release();
}
}
static class  C implements Runnable{
@Override
public void run() {
try {
a.acquire();
b.acquire();
print("C");
c.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class  D implements Runnable{
@Override
public void run() {
try {
c.acquire();
print("D");
d.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}


这段程序是输出A,B,C,D字符。程序使用了信号量保证了线程的执行顺序,使得输出A,B是并行,所以输出的顺序是随机的,[A,B],C,D这三个是串行,而且具有顺序的输出。

那么我们就可以用来完成并行计算的任务:

以下程序完成了假设的任务场景。现实生活中的应用嘛~可以刷ACM题的试试,说不定TLE的题就过了,但是据我所知有些OJ(codeforces)会检测多线程的使用,检测到就直接报错了。

package cacl;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
* Created by lewis on 2017/3/28.
*
*  并行计算
*
*/
public class Sums {

/**
* A:1+2+3+............+10000
* B:1+sqrt(1)+sqrt(3)+..........sqrt(10000)
* C:10+.............................+10[SUM(10000*10)] + C + D
* D:1*1+2*2+..................100*100 + C
* */
private static volatile Semaphore a,b,c,d;

private static volatile int resA,resB,resC,resD;

static {
a = new Semaphore(0);
b = new Semaphore(0);
c = new Semaphore(0);
d = new Semaphore(0);
}

public static void main(String []args){
ExecutorService executorService = Executors.newFixedThreadPool(4);
ArrayList<Callable<Integer>> list = new ArrayList<>();
list.add(new A());
list.add(new B());
list.add(new C());
list.add(new D());
List<Future<Integer>> futures = null;
try {
futures = executorService.invokeAll(list);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
executorService.shutdown();
}

for(Future<Integer>future:futures){
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
public static <T> void print(T s){
System.out.println(s);
}

static class  A implements Callable<Integer>{

@Override
public Integer call() throws Exception {

synchronized (this){
int res = 0;
for(int i = 0;i<10000;i++){
res += i;
}
resA = res;
a.release();
return resA;
}
}
}

static class  B implements  Callable<Integer>{

@Override
public Integer call() throws Exception {
synchronized (this) {
int res = 0;
for (int i = 0; i < 10000; i++) {
res += Math.sqrt(i);
}
resB = res;
b.release();
return resB;
}
}
}
static class  C implements  Callable<Integer>{

@Override
public Integer call() throws Exception {
synchronized (this){
a.acquire();
b.acquire();
int res = 0;
for(int i = 0;i<100;i++){
res += i*i;
}
resC = res + resA + resB;
c.release();
return resC;
}
}
}
static class  D implements  Callable<Integer>{

@Override
public Integer call() throws Exception {
synchronized(this){
c.acquire();
int res = 0;
for(int i = 0;i<10000;i++){
res += 10;
}
resD = res + resC + resA +resB;
d.release();
return resD;
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息