分类: Java
2012-12-08 17:10:58
什么是进程
一个进程就是在一个运行的程序,它有自己独立的内存空间,一组系统资源,每个进程的内部数据和状态都是独立的,例如在window是同时打开多个记事本,虽然它们所运行的程序代码都是一样的,但是所使用的内存空间是独立的,互不干扰。
1.2什么是线程
线程与进程相似,是一段完成某个特定功能的代码,是程序中单个顺序的流控制;但与进程不同的是,同类的多个线程共享一块内存空间和一组系统资源,而线程本身的数据通常只有微处理器的寄存器数据,以及一个供程序执行时使用的堆栈
1.3进程与线程的区别
1. 进程:每个进程都有独立的代码和数据空间(进程上下文) ,进程切换的开销大。
2. 线程:轻量的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小。
3. 多进程:在操作系统中,能同时运行多个任务程序。
4. 多线程:在同一应用程序中,有多个顺序流同时执行。
1.4线程创建的两种方式
采用继承Thread类创建线程
该方法比较简单,主要是通过继承java.lang.Thread类,并覆盖Thread类的run()方法来完成线成的创建。Thread 类是一个具体的类,即不是抽象类,该类封装了线程的行为。要创建一个线程,程序员必须创建一个从 Thread 类导出的新类。Thread类中有两个最重要的函数run()和start()。
通过实现Runnable接口创建线程
该方法通过生成实现java.lang.Runnable接口的类。该接口只定义了一个方法run(),所以必须在新类中实现它。但是 Runnable 接口并没有任何对线程的支持,我们还必须创建 Thread 类的实例,这一点通过 Thread 类的构造函数
public Thread(Runnable target);来实现。
2 单线程和多线程性能比较
以使用蒙特卡罗概率算法求π为例,进行单线程和多线程时间比较
2.1什么是蒙特卡罗概率算法
蒙特卡罗法(Monte Carlo method)是以概率和统计的理论、方法为基础的一种计算方法,将所求解的问题同一定的概率模型相联系,用电子计算机实现统计模拟或抽样,以获得问题的近似解,故又称统计模拟法或统计试验法。 --百度百科
蒙特卡罗求算法求π
第一步
画正方形和内切圆
第二步
变换表达式
正方形面积As=(2R)^2
圆的面积Ac=πR^2
Ac/As=(2R)^2/πR^2
π=4As/Ac
令P=As/Sc,则π=4P
第三步
重复N次实验求平均值
在正方形区域内随机生成一个点A,若A落在圆区域内,M++
P=M/N
π=4P,N的取值越大,π的值越精确
2.2 java代码实现算法
N取值为10000万,多线程的数为100,每个线程执行100万次模拟实验
线程实现
import java.util.concurrent.CountDownLatch;
public class ProModel implements Runnable {
public int N;//随机实验的总次数 public static int M;//随机点落在圆中的次数
private int id; private final CountDownLatch doneSignal; OBJ semaphore; public ProModel(int id,CountDownLatch doneSignal,int N,OBJ semaphore2){ this.id=id; this.doneSignal=doneSignal; this.N=N; this.semaphore=semaphore2; M=0; } public void run(){
int tempM=0; for(int i=0;i<N;i++){ if(isInCircle()){ tempM++; } } synchronized (semaphore) { add(tempM); } doneSignal.countDown();//使end状态减1 }
public void add(int tempM){ System.out.println(Thread.currentThread().getName()); M=M+tempM; System.out.println(M); } //随机产生一个在正方形区域的点,判断它是否在圆中 public boolean isInCircle(){
double x=Math.random(); double y=Math.random();
if((x-0.5)*(x-0.5)+(y-0.5)*(y-0.5)<0.25) return true; else return false; } public static int getTotal(){ return M; } } |
多线程Main实现
import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;
public class MutliThread { public static void main(String[] args) throws InterruptedException { long begin=System.currentTimeMillis(); int threadSize=100; int N=1000000; OBJ semaphore = new OBJ(); CountDownLatch doneSignal = new CountDownLatch(threadSize);
ProModel[] pros=new ProModel[threadSize];
//设置特定的线程池,大小为threadSizde System.out.println("begins!"); ExecutorService exe = Executors.newFixedThreadPool(threadSize); for(int i=0;i exe.execute(new ProModel(i+1,doneSignal,N,semaphore));
try{ doneSignal.await(); //等待end状态变为0, }catch (InterruptedException e) { // TODO: handle exception35 e.printStackTrace(); }finally{ System.out.println("ends!"); System.out.println(4*(float)ProModel.getTotal()/(float)(threadSize*N)); } exe.shutdown();
long end=System.currentTimeMillis(); System.out.println("used time(ms):"+(end-begin)); } } class OBJ{} |
单线程Main实现
import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;
public class SingleThread {
public static void main(String[] args) { long begin=System.currentTimeMillis();
int threadSize=1; int N=100000000; OBJ semaphore = new OBJ(); CountDownLatch doneSignal = new CountDownLatch(threadSize);
ProModel[] pros=new ProModel[threadSize];
//设置特定的线程池,大小为5 System.out.println("begins!"); ExecutorService exe = Executors.newFixedThreadPool(threadSize); for(int i=0;i exe.execute(new ProModel(i+1,doneSignal,N,semaphore));
try{ doneSignal.await(); //等待end状态变为0, }catch (InterruptedException e) { // TODO: handle exception35 e.printStackTrace(); }finally{ System.out.println("ends!"); System.out.println(4*(float)ProModel.getTotal()/(float)(threadSize*N)); } exe.shutdown();
long end=System.currentTimeMillis(); System.out.println("used time(ms):"+(end-begin)); } } |
运行结果比较
|
π |
Time |
多线程(10*10000) |
2.51108 |
used time(ms):44 |
单线程(100000) |
3.1306 |
used time(ms):28 |
|
π |
Time |
多线程(100*1000000) |
3.141768 |
used time(ms):35203 |
单线程(100000000) |
3.1415854 |
used time(ms):13582 |
根据运行结果看,由于多线程运行时要进行分配资源的操作,在单机上的运行速度并没有单线程效率高。