单线程即串行方式计算素数
package prime.witersen;
public class pc_serial {
private static final int NUM_END = 200000;
public static void main(String[] args) {
int counter = 0;
int i;
long startTime = System.currentTimeMillis();
for (i = 0; i < NUM_END; i++) {
if (isPrime(i))
counter++;
}
long endTime = System.currentTimeMillis();
long timeDiff = endTime - startTime;
System.out.println("执行时间: " + timeDiff + " ms");
System.out.println("素数个数: " + counter);
}
private static boolean isPrime(int x) {
int i;
if (x <= 1)
return false;
for (i = 2; i < x; i++) {
if ((x % i == 0) && (i != x))
return false;
}
return true;
}
}
静态负载平衡方式1,即在进行编程时为每个线程分配工作,指定每个线程的计算范围
按照均分的方式分配每个线程的计算量
package prime.witersen;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
public class pc_static_1 {
// 素数范围 0-NUM_END
private static final int NUM_END = 200000;
// 对素数计数
private static AtomicInteger COUNT = new AtomicInteger(0);
// 线程数
private static int THREAD_NUM = 10;
public static void main(String[] args) throws InterruptedException {
// 以线程数作为计数依据 达到等待子线程结束目的
CountDownLatch latch = new CountDownLatch(THREAD_NUM);
// 按照均分的方式分配每个线程的计算量
int base = NUM_END / THREAD_NUM;
// 创建指定数量的线程
TestThread[] threads = new TestThread[THREAD_NUM];
for (int i = 0; i < THREAD_NUM; i++) {
threads[i] = new TestThread(base * i + 1, base * i + base, latch);
threads[i].setName((i+1)+"");
}
// 开始计时
long startTime = System.currentTimeMillis();
// 启动线程
for (int i = 0; i < THREAD_NUM; i++) {
threads[i].start();
}
// 等待子线程结束
latch.await();
// 结束计时
long endTime = System.currentTimeMillis();
System.out.println("总耗时:" + (endTime - startTime) + " ms");
System.out.println("素数个数:" + COUNT.get());
}
// 线程类
static class TestThread extends Thread {
int startPos, endPos;
CountDownLatch latch;
public TestThread(int start, int end, CountDownLatch latch) {
this.startPos = start;
this.endPos = end;
this.latch = latch;
}
public void run() {
// 每个线程内的开始计时
long startTime = System.currentTimeMillis();
getPrime(startPos, endPos);
// 每个线程内的结束计时
long endTime = System.currentTimeMillis();
System.out.println("单线程" + Thread.currentThread().getName() + "耗时:" + (endTime - startTime) + " ms");
latch.countDown();
}
}
// 判断是否为素数
static boolean isPrime(int x) {
int i;
if (x <= 1)
return false;
for (i = 2; i < x; i++) {
if ((x % i == 0) && (i != x))
return false;
}
return true;
}
// 判断一个给定范围内的素数个数
static void getPrime(int start, int end) {
for (int i = start; i <= end; i++) {
if (isPrime(i)) {
COUNT.getAndIncrement();
}
}
}
}
静态负载平衡方式2,即在进行编程时为每个线程分配工作,指定每个线程的计算范围
不按照均分的方式为每个线程分配工作量,而是手动调整,因为素数判断到后面数字越大处理耗费的时间越长
package prime.witersen;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
public class pc_static_2 {
// 素数范围 0 - ?
private static final int NUM_END = 200000;
// 最大并发数
private static final int CPU_CORE_NUM = 5;
// 对素数计数
private static AtomicInteger integer = new AtomicInteger();
public static void main(String[] args) {
// 创建一个定长的线程池 可控制线程的最大并发数 超出的线程会在队列中等待
ExecutorService service = Executors.newFixedThreadPool(CPU_CORE_NUM);
// 素数判断到后面数字越大处理耗费的时间越长 速度越慢 此处虽然为均分 但是如果要加快计算速度 可以将大范围的数据加到前面的线程
// 如1-80000 80001-100000
// 其中的 1 2 3 4 5为序号 可使打印结果更直观
MyTask t1 = new MyTask(1, 40000, 1);
MyTask t2 = new MyTask(40001, 80000, 2);
MyTask t3 = new MyTask(80001, 120000, 3);
MyTask t4 = new MyTask(120001, 160000, 4);
MyTask t5 = new MyTask(160001, 200000, 5);
Future<Integer> s1 = service.submit(t1);
Future<Integer> s2 = service.submit(t2);
Future<Integer> s3 = service.submit(t3);
Future<Integer> s4 = service.submit(t4);
Future<Integer> s5 = service.submit(t5);
// 开始计时
long startTime = System.currentTimeMillis();
try {
s1.get();
s2.get();
s3.get();
s4.get();
s5.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
// 结束计时
long endTime = System.currentTimeMillis();
System.out.println("总耗时:" + (endTime - startTime) + " ms");
System.out.println("素数个数:" + integer.get());
service.shutdown();
}
// 获取线程有继承Thread类、实现runnable接口、实现callable接口三种方法 这里使用第三种
static class MyTask implements Callable<Integer> {
int startPos, endPos, sign;
MyTask(int start, int end, int sign) {
this.startPos = start;
this.endPos = end;
this.sign = sign;
}
@Override
public Integer call() throws Exception {
// 每个线程内的开始计时
long startTime = System.currentTimeMillis();
getPrime(startPos, endPos);
// 每个线程内的结束计时
long endTime = System.currentTimeMillis();
System.out.println("单线程" + sign + "耗时:" + (endTime - startTime) + " ms");
return integer.get();
}
}
// 判断是否为素数
static boolean isPrime(int x) {
int i;
if (x <= 1)
return false;
for (i = 2; i < x; i++) {
if ((x % i == 0) && (i != x))
return false;
}
return true;
}
// 判断一个给定范围内的素数个数
static void getPrime(int start, int end) {
for (int i = start; i <= end; i++) {
if (isPrime(i)) {
integer.getAndIncrement();
}
}
}
}
动态负载平衡方式
即多线程中的每个线程不指定分配量,每个线程拿到哪个任务就计算哪个任务,这种方式效率最高
package prime.witersen;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class pc_dynamic {
// 素数范围 0 - NUM_END
private static AtomicInteger NUM_END = new AtomicInteger(200000);
// 最大并发数
private static final int CPU_CORE_NUM = 32;
// 线程数
private static int THREAD_NUM = 10;
// 对素数计数
private static AtomicInteger COUNT = new AtomicInteger();
public static void main(String[] args) throws InterruptedException {
// 创建一个定长的线程池 控制线程的最大并发数 超出的线程会在队列中等待
ExecutorService service = Executors.newFixedThreadPool(CPU_CORE_NUM);
// 用于批量添加线程
List<Callable<Integer>> callableList = new ArrayList<Callable<Integer>>();
// 创建线程
for (int i = 0; i < THREAD_NUM; i++) {
final int sign = i;
// 直接使用匿名内部类
callableList.add(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
// 每个线程内的开始计时
long startTime = System.currentTimeMillis();
while (NUM_END.get() != 0) {
int temp = NUM_END.getAndDecrement();
// 打印空内容不能去掉
System.out.print("");
if (isPrime(temp)) {
COUNT.getAndIncrement();
}
}
// 每个线程内的结束计时
long endTime = System.currentTimeMillis();
System.out.println("单线程" + sign + "耗时:" + (endTime - startTime) + " ms");
return COUNT.get();
}
});
}
// 开始计时
long startTime = System.currentTimeMillis();
service.invokeAll(callableList, 10000, TimeUnit.SECONDS);
// 结束计时
long endTime = System.currentTimeMillis();
// 及时关闭
service.shutdown();
System.out.println("总耗时:" + (endTime - startTime) + " ms");
System.out.println("素数个数:" + COUNT.get());
}
// 判断是否为素数
static boolean isPrime(int x) {
int i;
if (x <= 1)
return false;
for (i = 2; i < x; i++) {
if ((x % i == 0) && (i != x))
return false;
}
return true;
}
}
原创文章,作者:witersen,如若转载,请注明出处:https://www.witersen.com