在计算机的世界里,当我们探讨并行的时候,实际上是指,一系列的任务在计算机中同时运行,比如在浏览器网页的时候还能打开音乐播放器,在撰写邮件的时候,收件箱还能接受新的邮件。在单cpu的计算机中,其实并没有真正的并行,他只不过是CPU时间中快速轮转调度带给你的错觉,而这种错觉让你产生了他们真的在同一时刻同时运行。当然如果市多核CPU,那么并行运行还是真实存在的。
线程
现在几乎所有的操作系统都支持多任务执行,对计算机来说每一个任务就是一个进程(process),在每一个进程内部至少要有一个线程(thread)在运行中,有时线程也称之为轻量级进程。
线程是程序执行的一个路径,每个线程都有自己的局部变量表、程序计数器(指向正在执行的指令指针)以及各自的生命周期,现代操作系统中一般不止一个线程在运行,当启动一个java虚拟机(JVM)时,从操作系统开始就会创建一个新的进程(JVM进程),JVM进程中将会派生或者创建很多线程。
尝试并发实战:
假设我想写一个程序,既想听音乐又想看新闻,那么我尝试写了如下程序:
package thread.test;
import java.util.concurrent.TimeUnit;
public class TestThread {
//main
public static void main(String [] args){
browseNews();
enjoyMusic();
}
//浏览新闻
public static void browseNews(){
for(;;){
System.out.println("browse news");
sleep(1);
}
}
//享受音乐
public static void enjoyMusic(){
for(;;){
System.out.println("enjoy music");
sleep(1);
}
}
//sleep
public static void sleep(int seconds){
try {
TimeUnit.SECONDS.sleep(seconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
打印结果如下:
browse news
browse news
browse news
browse news
browse news
browse news
发现一个问题就是我一直在看新闻但是没有听音乐,这样我就没有实现听音乐和看新闻的并行。
那么我们怎么改造这个程序让他既看新闻又可以听音乐呢?
那么我们就要引入Thread的Class的概念了。话不多说咱们先看看,Thread的神奇效果。
修改main方法,初始化一个thread,让浏览新闻放在线程里面。
//main
public static void main(String [] args){
new Thread(){
@Override
public void run(){
browseNews();
}
}.start();
enjoyMusic();
}
运行程序得到如下结果:
enjoy music
browse news
enjoy music
browse news
browse news
enjoy music
enjoy music
browse news
enjoy music
browse news
既可以浏览新闻又可以听音乐,实现了我们的并行。
修改main方法我们再做一个是实验:
//main
public static void main(String [] args){
enjoyMusic();
new Thread(){
@Override
public void run(){
browseNews();
}
}.start();
}
运行结果
enjoy music
enjoy music
enjoy music
enjoy music
enjoy music
enjoy music
我们发现我们即使用了thread但是还是没有实现我们的并发,原因在哪里呢?
原因是 enjoyMusic();永远不会停止,线程永远没有启动的机会。反过来思考为什么thread启动之后,里面是一个死循环,下面的方法还是可以得到cpu呢?
创建一个线程,并且重写run方法,将enjoyMusic交给它执行。
启动新的线程,只有调用了thread的start方法,才代表派生了一个新的线程,否则Thread和其他普通的java对象没什么区别,start方法是一个立即返回方法并不能造成阻塞。