一、进程和线程的理解
我们可以把Windows中运行的每一个.exe理解为一个进程,这个进程里面又包含着诸多的线程,例如我们运行着QQ,这是一个进程,同时我们在这个进程里跑着聊天、文件传输、视频语音、微云等线程,进程就相当于我们开启了某项服务,服务有在做不同的事。
单线程和多线程的效率自然不必赘述,当然多线程要快,这也是为什么我们从最开始的单核CPU发展到现在的多核多线程,单线程就像我们聚餐去了一家小饭店,获取了吃饭服务,只是这家小店是夫妻档,只有一个厨师,当人多或者点菜较多时只能一个一个来,毕竟只有一个厨子一个锅;多线程就像我们去了大饭店,我们同样只是点击了吃饭服务,但有N多的进程同时为我们服务,洗菜择菜切菜的N个进程、烧菜的N个进程、上菜的N个进程,上菜的效率固然要高出很多。CPU就相当于大堂经理,因为有多个线程提供调用。多线程是异步的,烧土豆丝的和烧红烧肉的并不相互影响,线程的调用也是随机的。一个进程的运行至少一个线程在运行响应,饭店里都在闲着,说明没有人点吃饭的服务。
这些都被詹姆斯.高斯林涉及到了Java里面。这些线程都在Java虚拟机里默默的运行着,如主函数main()方法。
public static void main(String[] args) { System.out.println(Thread.currentThread().getName()); }
控制台输出:main
二、多线程的实现
实现多线程有两种方法:1、继承thread类 2、实现Runable接口
2.1继承Thread类
源码:

从源码中我们可以看到Thread类实现了Runable接口,他们之间具有多态的关系。
代码案例:
public class MyThread extends Thread {
@Override
public void run(){
super.run();
System.out.println("Thread");
}
}
public class test001 {
public static void main(String[] args) {
Thread thread = new MyThread(); thread.start();
System.out.println("main");
}
}
运行结果:

从运行结果来看线程运行的顺序与调用的前后无关,我们首先准备了myThread线程,但是最打印的是main线程。如果换成run的话就会发现不同,必定先执行完调用的线程的代码才后继续向下执行。(对于新建的线程,调用两次及以上start()方法也会抛出异常)
2.1.1异步线程执行的随机性
public class MyThread extends Thread {
@Override
public void run(){
try {
for (int i = 0; i <10 ; i++) {
int time = (int) (Math.random()*1000);
Thread.sleep(time);
System.out.println(Thread.currentThread().getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class test001 {
public static void main(String[] args) {
try {
Thread thread = new MyThread();
thread.setName("myThread");
thread.start();
for (int i = 0; i < 10; i++) {
int time = (int) (Math.random()*1000);
Thread.sleep(time);
System.out.println(Thread.currentThread().getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
执行结果:

代码中为了体现线程的随即执行特性,使用随机随机数让线程进入休眠挂起状态,从而观察CPU执行线程的随机性。
Thread.java类中的start()方法仅仅是通知线程规划器此线程已经处于就绪状态,等待调用线程的run()方法,至于和时调用,
要等线程规划器来分配。代码中我们让两个线程都挂起,观察线程的调用情况,发现并无规律可循,和代码的先后顺序无关。