一、进程和线程的理解
我们可以把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()方法,至于和时调用,
要等线程规划器来分配。代码中我们让两个线程都挂起,观察线程的调用情况,发现并无规律可循,和代码的先后顺序无关。