.进程&线程(&java.lang.Thread)详解

一.进程与线程

进程

我们在进行操作电脑的时候,通常会打开浏览器,通讯工具等应用程序,这个时候CPU通过作业调度在内存中就会分配一些空间让它们处于宏观上的运行状态(处于可以被CPU执行的状态),而这部分空间资源就可以说是相应的进程占据的,很显然运行不同的程序需要不同的进程,在内存中也为它们分配独立,无共享的区域。静态描述进程的是PCB快(数据结构集),它是系统感知进程存在的唯一实体,通常包含进程名(或者标识符),用户名(或者用户标识号),家族关系。

进程的状态

就绪态:进程获得了除cpu以外的其他资源,进入抢占cpu的队列中

执行态:cpu正在执行该进程

阻塞态:进程继续执行的某个事件条件(如I/O设备)尚未具备

挂起态:处理机调度将进程调离内存进入外存

终止态:进程结束。(当我们撤销一个进程的时候,会通过PCB结构递归删除所有它的子进程,否者子进程可能处于无法控制的状态。)

(撤销进程的流程)

进程阻塞与挂起

阻塞详细流程图:

   

阻塞与挂起的区别:

1.首先阻塞是被动行为,当资源完备后,任然受cpu调度进入就绪状态,而挂起是主动行为,进程外存后,不受cpu作业调度,通过resume()函数进入就绪态。

2.发生原因不同:阻塞原因是针对这单个进程等待发生的条件不具备,而挂起原因内存资源有限暂时调离内存的过程。

线程

线程也称为轻型进程。线程的作用域在单个特定的线程内。一个进程内支持多个线程。这些线程的特点是:共享一定的内存区和数据。它们是彼此相互独立的,可以并发进行,宏观上看来是同时运行的,但实际上CPU在一个时刻只能处理一个子任务,分时操作系统采用了“时间片的策略”,即CPU将时间切割为时间片,然后将这些时间片分配给这些程序,只有获得时间片的程序才被执行。还有一个概念叫做主线程,它是进程初始化后自动启动的线程,如java里面的main。

进程与线程的区别

资源方面:一个进程包含多个线程,同类的多个线程共享一块内存和数据资源,而进程之间(包括子进程与父进程之间)是完全独立的,不存在资源的共享。

功能方面:进程是并发程序执行过程中资源分配的基本单元,线程是程序运行与调度的基本单元。

处理机的调度

(图片来自:http://www.cnblogs.com/dyllove98/p/3249243.html)

cpu调度发生的情况总结:

(1)创建进程:当创建新进程时,要决定运行父进程还是子进程;

(2)进程终止:每当一个进程终止时,必须进行调度;从就绪队列中选择要执行的下一个进程;

(3)等待事件:运行进程由于等待I/O、信号量或其他原因而不得不放弃CPU,这样就必须选择另一个进程投入运行。

(4)中断发生:当I/O设备完成时后会发出I/O中断,原先等待I/O的进程就从阻塞态转换为就绪态。调度程序要决定是调用就绪队列的进程,还是选择被打断的进程。

(5)运到到时:当进程进程分配的时间片用完,此时选择新的进程投入运行。

(很明显挂起的进程不需要cpu进行作业调度)

二.进程的优先级

对于所有线程都具有它自己的优先级,优先级高的首先被CPU执行,当某个线程处于运行状态时,那些尚未拥有优先级的处于可运行状态的线程会自动获得优先级。还存在另一种情况,当某个线程在运行时,一个更高优先级的线程处于可运行状态,这是这个线程被立即执行,这称为先占式调度。

三.线程的开发方法

1.实现Runnable接口实现它的run()方法

2.继承Thread类,覆盖它的run()方法----Thread已经实现了Runnable接口实现了run方法,因此继承Thread的类是覆盖run()方法

(Runnable实现线程解决了java单一继承的局限性)

四.线程池

背景:例如web服务器,数据库服务器,文件服务器等服务器端应用程序,都面临这来着客户端的请求,这些请求的整体特点是:单个任务处理的时间很短,但是请求的数目巨大

瓶颈:对于在进程内划分线程已经是个很大的改进,但仍然存在以下问题,对于每个到达服务器端的请求,单独为它们创建一个线程,将请求处理完后,再将线程销毁,然后线程创建与销毁的时间比处理请求的时间要多得多。同时线程过多,也会消耗内存。

改进:初始的时候便创建一个线程池(拥有i个线程),当请求到达时便拥有线程池中的某个线程(免去了创建时间),当线程池中的所有线程都被占据的时候,其他请求需要等待,占据线程的请求处理完后,线程又空余出来,新的请求可以进入。此处会有一定的等待时间,但和原来繁琐的线程创建和销毁相比,性能改进不少,同时线程池的构建也需要不断优化。

五.线程的状态以及运行控制

线程的运行状态

上述表明了线程在运行过程中的5种状态:

初始化状态:通过new实例化了一个线程对象,但该对象是空的并没有分配资源

可运行状态:通过start()方法,为该线程分配了除了CPU外的所需资源(进入队列,排队等待CPU),处于Runnable状态

运行状态:线程调度控制CPU处理一个Runnable线程,这个时候才实际上执行run()函数的代码

阻塞状态:正在运行的线程由于某些事件尚未具备(例如:输入输出)从而进入进入阻塞状态,来到阻塞池等待

挂起状态:  A,通过调用sleep()方法使线程进入休眠状态,线程在指定时间内不会运行。
              B,通过调用join()方法使线程挂起,如果某个线程在另一个线程t上调用t.join(),这个线程将被挂起,直到线程t执行完毕为止。
              C,通过调用wait()方法使线程挂起,直到线程得到了notify()和notifyAll()消息,线程才会进入“可执行”状态。

(区别进程的挂起,线程不拥有资源,也不存在将资源放入外存中)

死亡状态:线程结束了(Dead),可由这些原因导致:1.该线程运行完毕。2.意外退出。3.父类线程控制其消亡。

线程的运行控制

1.线程的启动start()

public class test extends Thread{
public void run(){
while(true){
System.out.println("子线程运行中---");
   }
 }
}
public static void main(String args[]){
test t =new test();
t.start();
try{
Thread.sleep(2000);//父线程进入等待池等待
 }
catch(Exception e ){
}
t.stop();
}//在上述实例中,通过main主线程创建了一个子线程,他们是相互独立,并发执行,但是父线程可以控制子线程的状态,例如stop()

2.休眠(sleep)与挂起(yield),join

相同:休眠与挂起都会使线程暂停处于等待状态

区别:休眠可以设定时间,并且期间任何优先级的线程都可以由可运行状态变为可执行状态,而挂起不可以设定时间,只有同等优先级的线程可以变成可执行状态

join立即执行方法

class test1 extends Thread{
    static int count = 0;
    public void run(){
        for(int i=0;i<5;i++){
            count++;
        }
    }
}
public class join {
public static void main(String ats[]){
    test1 t = new test1() ;
    try {
        t.start();
        t.join();//如果没有这条语句输出为0,当前输出为5
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println(test1.count);
}
}

3.wait()与sleep()区别

public class waitandsleep extends Thread{
static int number = 10;
public void firstMethod() throws Exception {
synchronized (this) {
number += 100;
System.out.println(number);
}
}
//下面是否加上static,又是一种同步锁,结果不一样
public synchronized void secondMethod() throws Exception {

//用于区别wait和sleep
//sleep(在Thread的静态方法)的时候仍然占有机锁,释放cpu
// Thread.sleep(2000);//当把改行注释转移到this.wait(2000)时,运行输出2100
//wait(Object的方法)的时候释放机锁,其他线程块可以进入,释放cpu
this.wait(2000);//输出110
number *= 200;
}
public void run() {
try {
firstMethod();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
waitandsleep ws=new waitandsleep();
ws.start();
ws.secondMethod();

ps:纯手打,图片是拍的书上的,勉强看的清楚,感觉自己写博文一直有个弊端,试图在一篇文章里面囊括一个大的知识工厂,但现在发现能将一个点讲清楚就非常非常困难,所以这篇失败的博文,还将继续改善,fighting!!

时间: 2024-08-14 06:12:36

.进程&线程(&java.lang.Thread)详解的相关文章

java java.lang.Long详解之一:toString()

文章看过后感觉受益匪浅,所以留下了以备温故:http://www.congmo.net/blog/2012/03/05/Long-toString/ 陆陆续续花了近两周时间看完了Long.java,可以说收获颇丰.也花了几天时间构思应该如何去写出来,苦于一直没有好的思路,又不能在这里干耗着浪费时间.所以就准备写出来了.很随意的写,想到哪里写到哪里.准备贴很多源码,附加我个人的理解. toString(long i, int radix) 首先让我们目睹下Long中强大的toString方法. p

java java.lang.Long详解之三 大显神通的位移运算(转)

http://blog.csdn.net/songylwq/article/details/9015581 http://www.congmo.net/blog/2012/03/11/Long-ByteShifting/

Java 线程--继承java.lang.Thread类实现线程

现实生活中的很多事情是同时进行的,Java中为了模拟这种状态,引入了线程机制.先来看线程的基本概念. 线程是指进程中的一个执行场景,也就是执行流程,进程和线程的区别: 1.每个进程是一个应用程序,都有独立的内存空间. 2.同一个进程中的线程共享其进程中的内存和资源. (共享的内存是堆内存和方法区内存,栈内存不共享,每个线程有自己的栈内存) 我们还需要了解以下基本内容: 1.什么是进程? 一个进程对应一个应用程序.例如:在Windows操作系统启动word就表示启动了一个进程.在Java开发环境下

Java线程池Executor框架详解

Java的线程既是工作单元,也是执行机制.从JDK 5开始,把工作单元与执行机制分离开来.工作单元包括Runnable和Callable,而执行机制由Executor框架提供. Executor框架简介在HotSpot VM的线程模型中,Java线程(java.lang.Thread)被一对一映射为本地操作系统线程.Java线程启动时会创建一个本地操作系统线程:当该Java线程终止时,这个操作系统线程也会被回收.操作系统会调度所有线程并将它们分配给可用的CPU.在上层,Java多线程程序通常把应

生产环境遇到的hashMap非线程安全问题java.lang.thread.waiting

写在前面:工作有几年了,从入门到现在,遇到也解决了一些问题.(当然,框架级别的暂时还没有)一直以来,都是从博客园以及其他各大社区搜罗出来的各种fix方法.目前稍有闲暇时间,在看过大V沈剑的博文后,我也鼓起勇气来书写博客,记录工作中遇到和解决的问题(其中当然也包括我在博园获取的各种解决方法:能找到原博文的小弟一定会注明出处.)因为总觉得自己水平不够,怕写出来的文章误导了别人.以下是这周生产环境遇到的一个问题,写出来供大家参考. 现象 周五一大早,车子都没停稳(电动车),群里就开始在询问谁最近的代码

Java多线程编程详解

线程的同步 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问. 由于我们可以通过 private 关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是 synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法:通过在方法声明中加入 synch

java异常处理机制详解

java异常处理机制详解 程序很难做到完美,不免有各种各样的异常.比如程序本身有bug,比如程序打印时打印机没有纸了,比如内存不足.为了解决这些异常,我们需要知道异常发生的原因.对于一些常见的异常,我们还可以提供一定的应对预案.C语言中的异常处理是简单的通过函数返回值来实现的,但返回值代表的含义往往是由惯例决定的.程序员需要查询大量的资料,才可能找到一个模糊的原因.面向对象语言,比如C++, Java, Python往往有更加复杂的异常处理机制.这里讨论Java中的异常处理机制. 异常处理 Ja

Java synchronized 关键字详解

Java synchronized 关键字详解 前置技能点 进程和线程的概念 线程创建方式 线程的状态状态转换 线程安全的概念 synchronized 关键字的几种用法 修饰非静态成员方法 synchronized public void sync(){ } 修饰静态成员方法 synchronized public static void sync(){ } 类锁代码块 synchronized (类.class){ } 对象锁代码块 synchronized (this|对象){ } syn

Java关键字synchronized详解

Java关键字synchronized详解 博客分类: Java综合 Java多线程thread互联网制造 synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D)运行完这个方法后再运行此线程A,没有的话,直接运行 它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法: 通过在方法声明中

Thread 详解

转自:http://www.mamicode.com/info-detail-517008.html 目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable接口 三Thread和Runnable的区别 四线程状态转换 五线程调度 六常用函数说明 使用方式 为什么要用join方法 七常见线程名词解释 八线程同步 九线程数据传递 本文主要讲了Java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的一些线程函数用法.概述等. 首先讲一下进程和线程的区