1.线程、进程
1.1 概念
进程:引入:为了程序能够并发执行,且为了对并发执行的程序加以描述和控制,引入了进程的概念。
(1)进程是程序的一次执行。
(2)进程是一个程序及其数据在处理机上顺序执行时所发生的活动。
(3)进程是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。
(4)进程是作为能够拥有资源和独立运行的基本单位。
线程: 引入:在操作系统中引入线程,是为了减少程序并发执行时锁付出的空间开销,使OS具有更好的并发性。1.2
1.2 线程与进程进行比较
线程具有许多传统进程所具有的特征,所以又称为轻量级进程或进程元,相应的把进程称为重量级的进程,传统进程相当于只有一个线程的任务,在引入了新城的操作系统中,通常一个进程都拥有若干个线程,至少也有一个线程。
相同点:
(1)调度:
(2)并发性:在引入了线程的操作系统中,进程之间或一个线程中的多个线程之间都可以并发执行。
(3)拥有资源:不论是传统的操作系统还是引入了线程的操作系统,进程都可以拥有资源,是系统中拥有资源的有个基本单位。
(4)系统开销:在某些操作系统中,线程的切换、同步和通信都无需操作系统内核的干预。
不同点:
(1)调度:在传统操作系统中,进程是拥有资源的基本和独立调度、分派的基本单位,在引入了线程的操作系统中,线程是调度和分派的基本单位,而进程是拥有资源的基本单位。
(2)并发性:
(3)拥有资源:进程拥有资源,线程自己不拥有资源(也有一点必不可少的资源)。但可以吧访问其他隶属进程的资源。
(4)系统开销:
a.在创建或撤销进程的时候,系统都要为之创建和回收进程控制块,分配或回收资源。如内存空间和I/O设备,系统开销明显大于线程创建或撤销时的开销。
b.在进程切换时,涉及到当前进程CPU环境的保存及新被调度运行进程的CPU环境的设置,而线程的切换则仅需要保存和设置少量寄存器内容,不涉及存储器管理方面的操作,所以,进程的代价远高于线程。
c.一个进程的多个线程具有相同的地址空间,在同步和通信的实现方面线程也比进程容易。
(5)进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
(6)进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮。
(7)每个独立的线程都有一个程序运行的入口,顺序执行序列和程序的入口,但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
1.3 线程的生命周期
1.3.1.线程处于就绪状态有以下几种方法
(1)调用sleep()方法
(2)调用wait()方法
(3)等待输入/输出完成
1.3.2.当线程处于就绪状态后,可以用以下几种方法使线程进入运行状态:
(1)线程调用notify()方法
(2)线程调用notifyAll()方法
(3)线程调用interrupt()方法
(4) 线程的休眠时间结束
(5)输入/输出结束
线程生命周期状态图:
2.线程的调度与控制
2.1 线程优先级
java虚拟机主要负责则线程的调度,获取CPU的使用权,目前有两种调度模型:分时调度模型和抢占调度模型;java使用抢占调度模型。
分时调度模型:所有线程轮流使用CPU的使用权,平均分配给每个线程占用CPU的时间片。
抢占调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么随机选择一个,优先极高的线程获得的CPU时间片相对多些。
例:
1 /* 2 线程优先级高的获取的时间片相对高 3 */ 4 class Threadtest04 5 { 6 public static void main(String[] args) 7 { 8 //线程优先级 9 System.out.println(Thread.MAX_PRIORITY); //10 优先级最高 10 System.out.println(Thread.MIN_PRIORITY); //1 优先级最低 11 System.out.println(Thread.NORM_PRIORITY); //5 默认优先级 12 Thread t1 = new P(); 13 t1.setName("t1"); 14 15 Thread t2 = new P(); 16 t2.setName("t2"); 17 18 System.out.println(t1.getPriority()); //默认优先级为5 19 System.out.println(t2.getPriority()); //默认优先级为5 20 //设置优先级 21 t1.setPriority(4); 22 t2.setPriority(9); 23 24 System.out.println(t1.getPriority()); //默认优先级为5 25 System.out.println(t2.getPriority()); //默认优先级为5 26 //启动线程 27 t1.start(); 28 t2.start(); 29 } 30 } 31 32 class P extends Thread 33 { 34 public void run() 35 { 36 for(int i=0;i<10;i++) 37 { 38 System.out.println(Thread.currentThread().getName()+"..."+i); 39 } 40 } 41 } 42 /* 43 运行结果: 44 10 45 1 46 5 47 5 48 5 49 4 50 9 51 t1...0 52 t2...0 53 t1...1 54 t2...1 55 t1...2 56 t2...2 57 t1...3 58 t2...3 59 t1...4 60 t2...4 61 t1...5 62 t2...5 63 t1...6 64 t2...6 65 t1...7 66 t2...7 67 t1...8 68 t2...8 69 t1...9 70 t2...9 71 请按任意键继续. . . 72 73 74 */
2.2 sleep方法
sleep和wait的区别:
(1)所属类不同
Thread.sleep() ; Object.wait()
(2)对于线程已经占有资源的处理
sleep在休息的时候,不释放资源 ; wait在等待的时候释放自己占用的资源
例:
1 /* 2 1.thread.sleep(毫秒) 3 2.sleep方法是一个静态方法 4 3.该方法作用:阻塞当前线程,将CPU让给其他线程 5 */ 6 class Threadtest05 7 { 8 public static void main(String[] args) throws InterruptedException 9 { 10 Thread t1 = new P(); 11 t1.setName("t1"); 12 t1.start(); 13 Thread.sleep(5000); 14 //t1.interrupt();打断线程的睡眠 15 for(int i = 0;i<10;i++) 16 { 17 System.out.println(Thread.currentThread().getName()+".."+i); 18 Thread.sleep(500);//阻塞主线程0.5秒 19 } 20 } 21 } 22 23 class P extends Thread 24 { 25 //被重写的方法不能抛出异常,在run方法的声明为置上不能呢使用Throws, 26 public void run() 27 { 28 for(int i = 0;i<10;i++) 29 { 30 31 try{ 32 Thread.sleep(1000);//让当前线程阻塞1s 33 }catch(InterruptedException e) 34 { 35 e.printStackTrace(); 36 } 37 System.out.println(Thread.currentThread().getName()+".."+i); 38 } 39 } 40 } 41 /* 42 运行结果: 43 main..0 44 t1..0 45 main..1 46 t1..1 47 main..2 48 main..3 49 main..4 50 t1..2 51 main..5 52 t1..3 53 main..6 54 main..7 55 t1..4 56 main..8 57 main..9 58 t1..5 59 t1..6 60 t1..7 61 t1..8 62 t1..9 63 请按任意键继续. . . 64 65 */