柯侧耳倾听者 - 云代码空间
—— 翱翔在Java世界的海洋之上
一、实验目的 1、理解线程的基本概念,掌握Java创建线程的方式。 2、掌握进程间参数传递方式以及线程同步、线程间通信的方法。 3、掌握线程池的工作原理和使用。
二、预习内容及要求(要求写出预习内容) 1、掌握不同类型的输入输出流类,标准数据流、文件流、数据输入输出流、对象流等。 2、编程时,应考虑异常处理。
三、实验内容、操作过程及实验结果记录 实验题1 阅读运行下列程序,分析其运行结果。 应用背景:分别使用单线程、多线程、线程池技术计算1000000~5000000之间的素数,并统计线程花费的计算时间,同时比较三种方式的速度快慢。 注意:在单线程模式中,使用循环分别判断每个数是否是质数;在多线程和线程池中,需要将计算任务分配给各个线程。 主要源代码见CalPrimeSingleThread.java、CalPrimeMultiThread.java以及CalPrimeThreadPool.java三个文档。 1、使用单线程计算素数。CalPrimeSingleThread.java代码如下: Package day01; import java.io.BufferedOutputStream; import java.io.DataOutputStream; import java.io.FileOutputStream; public class CalPrimeSingleThread { long primeCount = 0; public void calPrime(long start, long end) throws Exception { for (long i = start; i <end; ++i) { if (isPrime(i)) { primeCount++; } } } public boolean isPrime(long n) { for (long i = 2; i <= Math.sqrt(n); ++i) if (n % i == 0) return false; return true; } public static void main(String[] args) throws Exception { long start = 1000000; long end = 5000000; CalPrimeSingleThread prime = new CalPrimeSingleThread(); long startTime = System.nanoTime(); prime.calPrime(start, end); double estimatedTime = (System.nanoTime() - startTime) / 1000000000.0; System.out.printf("使用单线程计算%d~%d之间的质数\n",start, end); System.out.println("共有质数" + prime.primeCount + "个,花费时间为" + estimatedTime + "秒."); } }
2、使用多线程计算素数。CalPrimeMultiThread.java代码如下: Package day01; import java.io.BufferedOutputStream; import java.io.DataOutputStream; import java.io.FileOutputStream; import java.util.Vector; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; public class CalPrimeMultiThread { public static CountDownLatch counter; public static AtomicInteger numOfPrime; public static void main(String[] args) throws InterruptedException { long start = 1000000; long end = 5000000; int totalThreads = 10; CalPrimeMultiThread calPrime = new CalPrimeMultiThread(); calPrime.counter = new CountDownLatch(totalThreads); calPrime.numOfPrime = new AtomicInteger(0); long startTime = System.nanoTime(); long len = (end - start) / totalThreads; for (long i = 0; i < totalThreads; i++) { Thread t = new Thread(new PrimeThread(start + i * len, start + (i + 1) * len-1, calPrime)); t.start(); } calPrime.counter.await(); double estimatedTime = (System.nanoTime() - startTime) / 1000000000.0; System.out.printf("使用多线程计算%d~%d之间的质数\n",start, end); System.out.printf("共有质数%d个,花费时间为%.2f秒.\n", calPrime.numOfPrime.get(), estimatedTime); } } class PrimeThread implements Runnable { long startPos; long endPos; CalPrimeMultiThread result; public PrimeThread(long start, long end, CalPrimeMultiThread result) { this.startPos = start; this.endPos = end; this.result = result; } public boolean isPrime(long n) { for (long i = 2; i <= Math.sqrt(n); ++i) if (n % i == 0) return false; return true; } public void run() { for (long i = startPos; i <=endPos; ++i) { if (isPrime(i)) result.numOfPrime.incrementAndGet(); } result.counter.countDown(); } }
3、使用线程池计算素数。CalPrimeThreadPool.java代码如下: Package day01; import java.io.BufferedOutputStream; import java.io.DataOutputStream; import java.io.FileOutputStream; import java.util.Vector; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class CalPrimeThreadPool { // AtomicInteger提供原子方式更新int的值 public static AtomicInteger numOfPrime; public static void main(String[] args) throws InterruptedException { long start = 1000000; long end = 5000000; ExecutorService pool = Executors.newFixedThreadPool(20); CalPrimeThreadPool calPrime = new CalPrimeThreadPool(); calPrime.numOfPrime = new AtomicInteger(0); long startTime = System.nanoTime(); int range = 100000; for (long i = 0; i < (end - start) / range; i++) { pool.submit(new WorkThread(start + i * range, start + (i + 1) * range, calPrime)); } pool.shutdown(); pool.awaitTermination(10, TimeUnit.DAYS); double estimatedTime = (System.nanoTime() - startTime) / 1000000000.0; System.out.printf("使用线程池计算%d~%d之间的质数\n", start, end); System.out.printf("共有质数%d个,花费时间为%.2f秒.\n", calPrime.numOfPrime.get(), estimatedTime); } } class WorkThread implements Runnable { long startPos; long endPos; CalPrimeThreadPool result; public WorkThread(long startPos, Long endPos, CalPrimeThreadPool result) { this.startPos = startPos; this.endPos = endPos; this.result = result; } public boolean isPrime(long n) { for (long i = 2; i <= Math.sqrt(n); ++i) if (n % i == 0) return false; return true; } public void run() { for (long i = startPos; i < endPos; ++i) { if (isPrime(i)) result.numOfPrime.incrementAndGet(); } } }
四、实验过程中所遇问题思考与讨论(可写个人体会,或相关理论知识,根据个人具体情况选做) 通过这次的学习与实验,我初步掌握了网络编程中的一些用法和问题,也更加了解了网络编程中的一些基本概念,为今后更好的学习网络编程做好铺垫,在学习的过程中,我更加深刻的体会到与老师和同学间的交流与合作是多么的重要,所以在今后的学习与实验当中,要善于发现问题,更要及时与老师反馈问题所在,并与老师和同学交流学习经验,共同解决问题,这样才能更好的学好网络编程。
|