版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sureSand/article/details/82227381
毫无疑问,网上关于多线程的讲解很多,各种概念也很复杂,我们该怎么去理解多线程?该如何最直观的面对它,先看一段简单的代码:
package cn.com;
public class TestMainNoRunnable {
public static void main(String[] args) {
long startTime=System.currentTimeMillis(); //获取开始时间
double sum = 0;
for(int i=0;i<2000000000;i++){
sum += i;
}
System.out.println(sum);
long endTime=System.currentTimeMillis(); //获取结束时间
System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
}
}
这段代码做的事情是从1到2000000000的累加,最终输出:
1.99999999806711398E18
程序运行时间: 2761ms
好,那么我们当然可以将这段累加拆分到两个线程去执行,然后将两个线程的结果合并。
线程1:从0累加到800000000
package cn.com;
import java.util.concurrent.CountDownLatch;
public class TestRunnable1 implements Runnable{
double sum1 = 0;
@Override
public void run(){
for(int i =0;i<800000000;i++){
sum1 += i ;
}
}
}
线程2:从800000000累加到2000000000:
package cn.com;
import java.util.concurrent.CountDownLatch;
public class TestRunnable2 implements Runnable{
double sum2 = 0;
@Override
public void run(){
for(int i =800000000;i<2000000000;i++){
sum2 += i ;
}
}
}
主线程合并线程一和线程二的结果:
package testWSO2;
import java.util.concurrent.CountDownLatch;
public class TestRunnaleMain {
public static void main(String[] args) throws InterruptedException {
long startTime = System.currentTimeMillis(); // 获取开始时间
TestRunnable1 t1 = new TestRunnable1();
TestRunnable2 t2 = new TestRunnable2();
Thread t1s = new Thread(t1);
t1s.start();
Thread t2s = new Thread(t2);
t2s.start();
t2s.join();//待需要执行时间较长的t2线程结束再继续执行主线程,否则主线程结束了,t1和t2还没计算完
System.out.println("sum1= " + t1.sum1);
System.out.println("sum2= " + t2.sum2);
double sum =t1.sum1+t2.sum2;
System.out.println("sum3= " + sum);
long endTime = System.currentTimeMillis(); // 获取结束时间
System.out.println("程序运行时间: " + (endTime - startTime) + "ms");
}
}
最终输出:
sum1= 3.1999999926710899E17
sum2= 1.67999999880559053E18
sum3= 1.99999999807269939E18
程序运行时间: 1753ms
可以发现比直接累加1到2000000000节省了近一秒时间,大家这么一看是不是很直观的感受到两个多线程的好处了。
大家可以改成1到200的累加,会发现单线程会比两个线程还快,而且线程越多这里越慢,这里就可以理解了多线程上下文的切换也需要时间,所以一个cpu能执行的搓搓有余何必去切换多线程呢?就是说有时候并不是多线程就好,要合理根据自己的业务来设计多线程。
其中 t2s.join()是为了让执行时间较长的t2线程结束再继续执行主线程,否则主线程结束了,t1和t2还没计算完,这里并不是最好的办法,推荐使用Java自带的CountDownLatch计数器来解决这个问题。