进程与线程
理解进程与线程:
1.DOS有一个明显的特点,就是一旦病毒入侵,系统就会死机,因为传统的DOS系统是单进程处理方式,所以只有一个程序运行,其它程序无法运行。
而windows系统中,即使出现病毒,系统照样可以使用,因为windows系统是采用多进程处理方式,在同一个时间段上会有多个程序在运行。
2.对于word来说每次启动一个word实际上都是在操作系统上分配一个进程。而线程实际上是在进程的基础上进一步划分,从word来看可以把拼写检查当做一个线程进行处理。当然会同时存在多个线程。
一个进程相当于一个程序运行,比如我们打开world,打开excel,打开pps,打开QQ等等这是多个进程,即多个程序在运行。
而一个线程相当于一个程序中的一部分,比如在world中添加图片这种操作。
所以有进程才有线程。
3.如果一个进程没有了,线程一定会消失;但线程消失了,进程未必会消失。而且线程都是在进程的基础上并发同时运行。
4.下面来看进程与线程的概念:
进程是程序的动态执行过程,它经历了从代码加载,执行,到执行完毕的一个完整过程。这个过程也是进程本身从产生、发展,到最终消亡的一个过程。
多线程是实现并发机制的一个有效手段。进程和线程一样都是实现并发的基本单位。
理解多线程:如果现在同时有多个任务,则所有的系统的资源是共享的,被所有线程所公用,但是程序处理需要CPU,传统单核CPU来说同一个时间段会有多个程序执行,但是在同一个时间点上只能存在一个程序运行,也就是说所有的程序都要抢占CPU资源。但是当CPU已经发展到多核的状态了,在一个电脑上可能会存在多个CPU,这个时候就可以非常清楚的发现多线程操作间是如何进行并发的执行的。
5.java实现多线程:
两种方式:(1)继承Thread
(2)实现Runnable接口
先调用start方法,在执行run方法。这是为什么呢?打开Thread的类定义,在jdk的src.zip中全部是java的源程序代码,直到找到java.lang.Thread类的定义:
public synchronized void start(){
if(threadStatus != 0)
throw new IllegalThreadStateException();
start0();
if(stopBeforeStart){
stop0(throwableFromStop);
}
}
private native void start();
start()方法可能抛出异常。
stopBeforeStart是一个boolean型变量,native关键字表示由java调用本机操作系统函数的一个关键字。在java中,运行java程序调用本机的操作系统的函数已完成特定的功能。
证明:如果现在要想实现多线程的话,则肯定需要操作系统的支持,因为多线程操作系中牵涉到一个抢占CPU的情况,要等待CPU进行调度,这一点肯定需要操作系统的底层支持,所以使用了native调用本机的系统函数。而且在各个操作系统中实现底层代码肯定是不同的,所以使用native关键字也可以让JVM自动调整不同的JVM实现。
threadStatus也表示一种状态,如果线程已经启动了在调用start方法的时候就有可能产生异常。
继承Thread实现多线程:
class myThread extends Thread{
private String name;
public myThread(String name){//通过构造方法配置name属性
this.name = name;
}
public void run(){//重写run方法
for(int i = 0;i<10; i++){
System.out.println(name +"运行,i="+i);
}
}
}
public class ThreadDemo{
public static void main(String []args){
myThread mt1 = new MyThread("线程A");//实例化对象
mt1.start();//调用线程主体
mt1.start();//异常
}
}
Runnable接口:在java中可以通过实现Runnable接口的方式实现多线程,Runnable接口中只定义了一个抽象的方法。public void run();
在Runnable中并没有start()方法,那么怎样才能使用start()方法呢?在Thread类中有构造方方法public Thread(Runnable target ){}利用此构造方法启动多线程。
class MyThread implements Runnable{
private String name;
public MyThread(String name){
this.name = name;
}
public void run(){
for(int i = 0;i<10;i++){
System.out.Println(name+"运行,i = "+i);
}
}
}
public class myThreadDemo{
public static void main(String []args){
MyThread mt1 = new MyThread("线程A");//实例化对象
MyThread mt2= new MyThread("线程B");
Thread t1 = new Thread(mt1);//实例化Thread类对象
Thread t2 = new Thread(mt2);
t1.start();//启动多线程和
t2.start();
}
}
Thread类与Runnable接口的联系:
Thread 定义:
public class Thread extends Object implements Runnable 发现Thread类也是Runnable接口的子类,使用了代理的机制完成。
Thread类与Runnable接口的区别:
使用Thread类操作多线程的时候无法达到资源共享的目的,而使用Runnable接口实现的多线程操作可以实现资源共享。
Thead类与Runnable接口的使用结论:
实现Runnable接口比继承Thread类有如下明显的优点:
(1)适合多个相同程序的代码的线程去处理同一个资源。
(2)可以避免由于单继承局限所带来的影响。
(3)增强了程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。
线程的状态:
创建状态:准备好了一个多线程对象:Thread t = new Thread();
就绪状态:调用了start()方法,等待CPU进行调度。
运行状态:执行run方法
阻塞状态:暂时停止执行,可能将资源交给其他线程使用。
终止状态:(死亡状态):线程执行完毕了,不再使用了。