进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位)。
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)线程是一个程序里面不同的执行路径,线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。Windows操作系统是支持多线程的,它可以同时执行很多个线程,也支持多进程,因此Windows操作系统是支持多线程多进程的操作系统。Linux和Uinux也是支持多线程和多进程的操作系统。DOS就不是支持多线程和多进程了,它只支持单进程,在同一个时间点只能有一个进程在执行,这就叫单线程。
CPU执行原理:在同一个时间点上,一个CPU只能支持一个线程在执行。因为CPU运行的速度很快,一秒钟可以算好几亿次,因此我们看起来的感觉就像是多线程一样,CPU把自己的时间分成一个个小时间片,不同时间片执行不同的线程,虽然有几十个线程,但一样可以在很短的时间内把他们通通都执行一遍,但对我们人来说,CPU的执行速度太快了,因此看起来就像是在同时执行一样,但实际上在一个时间点上,CPU只有一个线程在运行。
多进程:多进程是指操作系统能同时运行多个任务(程序)。
多线程:多线程是指在同一程序中有多个顺序流在执行。什么才是真正的多线程?如果你的机器是双CPU,或者是双核,这确确实实是多线程。
线程声明周期:线程是一个动态执行的过程,它也有一个从产生到死亡的过程。
- 新建状态:使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
- 就绪状态:当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
- 运行状态:如果就绪状态的线程获取CPU资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
- 阻塞状态:如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
- 等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
- 同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
- 其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
死亡状态:一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。
源代码:
1 public class MyThread { 2 public static void main(String[] args) { 3 ZykThread ZYK=new ZykThread(); 4 ZYK.setName("线程A"); 5 ZYK.start(); 6 ZykThread ZYK1=new ZykThread(); 7 ZYK1.setName("线程B"); 8 ZYK1.start(); 9 ZykThread ZYK2=new ZykThread(); 10 ZYK2.setName("线程C"); 11 ZYK2.start(); 12 } 13 static class ZykThread extends Thread{ 14 private int count=0; 15 public void run(){ 16 while (count<100){ 17 try { 18 Thread.sleep(2000); 19 }catch (InterruptedException e){ 20 e.printStackTrace(); 21 } 22 count++; 23 if(count%2==0){ 24 System.out.println(Thread.currentThread().getName()+"输出偶数:"+count); 25 } 26 } 27 } 28 } 29 }
《二、通过实现 Runnable 接口来创建线程》
1 public class MyRunnable { 2 3 public static void main(String args[]) { 4 RunnableDemo R1 = new RunnableDemo( "Thread-1"); 5 R1.startThread(); 6 7 RunnableDemo R2 = new RunnableDemo( "Thread-2"); 8 R2.startThread(); 9 } 10 } 11 12 13 //定义线程的类实现Runnable接口 14 class RunnableDemo implements Runnable { 15 private Thread t; 16 private String threadName; 17 18 RunnableDemo( String name) { 19 threadName = name; 20 System.out.println("Creating " + threadName ); 21 } 22 23 public void run() { 24 System.out.println("Running " + threadName ); 25 try { 26 for(int i = 0; i <100; i++) { 27 System.out.println(threadName + ", " + i); 28 // 让线程睡眠一会 29 Thread.sleep(500); 30 } 31 }catch (InterruptedException e) { 32 System.out.println(threadName + " interrupted."); 33 } 34 System.out.println("Thread " + threadName + " exiting."); 35 } 36 37 //定义启动线程的方法 38 public void startThread () { 39 System.out.println("Starting " + threadName ); 40 if (t == null) { 41 //创建实现Runnable接口的线程对象时,需要将该对象经过Thread构造器 42 t = new Thread (this, threadName); 43 //启动线程 44 t.start (); 45 } 46 } 47 }