java并行计算--Semaphore信号量的简单使用
2017-03-29 22:00
489 查看
多线程不仅适用于IO密集型任务,而且在计算型密集型任务也是同样很有优势,最直观的就是快嘛!先来假设一个任务场景:
我们通过这种信号量的阻塞方式来实现线程的执行方式,通过 acquire()阻塞, release() 来释放阻塞。来看一段小程序:
这段程序是输出A,B,C,D字符。程序使用了信号量保证了线程的执行顺序,使得输出A,B是并行,所以输出的顺序是随机的,[A,B],C,D这三个是串行,而且具有顺序的输出。
那么我们就可以用来完成并行计算的任务:
以下程序完成了假设的任务场景。现实生活中的应用嘛~可以刷ACM题的试试,说不定TLE的题就过了,但是据我所知有些OJ(codeforces)会检测多线程的使用,检测到就直接报错了。
假设场景:
有一个计算任务:需要先计算出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; } } } }
相关文章推荐
- 使用栈计算多项表达式的简单实现--java
- 多线程 : Java 信号量 Semaphore 使用
- Java多线程之信号量(Semaphore)的使用
- Java中Semaphore(信号量)的使用
- JAVA并行计算之ForkJoinTask使用样例
- 老紫竹JAVA提高教程-信号量(Semaphore)在生产者和消费者模式的使用
- java多线程-Semaphore信号量使用 介绍 信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源
- java多线程-Semaphore信号量使用
- 【并行计算】使用MPI实现简单的并行素数筛法
- Java中Semaphore(信号量)的使用
- java多线程--信号量Semaphore的使用
- 信号量 java.util.concurrent.Semaphore的使用
- Java中使用信号量——Semaphore
- java多线程-Semaphore信号量使用
- Java使用BigDecimal精确计算的简单公式计算器
- Java中Semaphore(信号量)的使用
- Java 递归调用 最简单计算1-n的和,不用使用循环语句,一条语句搞定
- Java中Semaphore(信号量)的使用
- Java使用BigDecimal精确计算的简单公式计算器
- 使用wait、notify简单实现并行计算