这一章节我们来讨论一下为什么需要并发?
答案:快和促进代码设计的改进
1.快
先对比一下下面的两个例子:
package com.ray.ch17;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) throws InterruptedException {
long startTime = System.currentTimeMillis();
System.out.println("--程序开始--");
System.out.println("working...");
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
list.add(i);
Thread.sleep(100);// 某些操作所需要的时间
}
ArrayList<Integer> list2 = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
list2.add(i);
Thread.sleep(100);// 某些操作所需要的时间
}
System.out.println("--程序结束--");
long endTime = System.currentTimeMillis();
System.out.println("" + (endTime - startTime));
}
}
输出:
--程序开始--
working...
--程序结束--
2015
package com.ray.ch17;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
public class Test2 {
public static void main(String[] args) throws InterruptedException {
long startTime = System.currentTimeMillis();
System.out.println("--程序开始--");
System.out.println("working...");
CountDownLatch countDownLatch = new CountDownLatch(2);
ThreadOne threadOne = new ThreadOne(countDownLatch);
ThreadTwo threadTwo = new ThreadTwo(countDownLatch);
Thread thread1 = new Thread(threadOne);
Thread thread2 = new Thread(threadTwo);
thread1.start();
thread2.start();
countDownLatch.await();
System.out.println("--程序结束--");
long endTime = System.currentTimeMillis();
System.out.println("" + (endTime - startTime));
}
}
class ThreadOne implements Runnable {
private CountDownLatch countDownLatch;
public ThreadOne(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
list.add(i);
try {
Thread.sleep(100);// 某些操作所需要的时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
countDownLatch.countDown();
}
}
class ThreadTwo implements Runnable {
private CountDownLatch countDownLatch;
public ThreadTwo(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
list.add(i);
try {
Thread.sleep(100);// 某些操作所需要的时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
countDownLatch.countDown();
}
}
输出:
--程序开始--
working...
--程序结束--
1016
从上面两个例子的输出可以看出,大家同样都是向两个list里面添加数据,中间都是有操作时间,但是第二个使用并发,也就是多线程的例子明显比上面的那个要快。
因为在我们的操作中,不可避免的有些是需要等待的,如果按照第一个例子的做法,就会形成阻塞,操作是一个一个的按顺序完成,不可以逾越,但是第二种使用多线程,充分利用现在的多cup来处理任务,不再是单线程的线性操作。
我们上面的例子只是小数据量的例子,当上升到处理百万基本甚至亿级的时候,多线程的性能就会更加的显示出来。
2.促进代码设计的改进
例子:
package com.ray.ch16;
public class Test {
public static void main(String[] args) {
//操作1
//操作2
//操作3
}
}
在平常的编程里面,我们经常无意识的就把大量的操作放在同一个方法里面,像上面的那段代码。
但是,当引入并发后,由于只是某个操作需要并发,其他的不需要,那么现在就要去程序员把这个方法分解处理,形成各种方法,然后进一步方法间的解耦。
package com.ray.ch16;
public class Test {
public void methodA() {// 操作1
}
public synchronized void methodB() {// 操作2
}
public void methodC() {// 操作3
}
public void method() {
methodA();
methodB();
methodC();
}
public static void main(String[] args) {
new Test().method();
}
}
上面的代码是改进后的代码,而且,当上面的方法分解开来,其实每一个小的方法可能即使其他方法的某一个操作,再把其他的方法分解解耦,最后达到代码的整体改进。
总结:这一章节通过两个例子的对比,得出为什么需要并发。
这一章节就到这里,谢谢。
-----------------------------------