<基础-1> java并发编程基础

[b]一、 java并发编程基础[/b]
[b]1.1 程序、进程和线程[/b]
1.程序是静态的概念,是一组指令的集合,是永久的。可以比作是电影的胶片。
2.进程是动态的概念,是程序及其数据在计算机上的一次执行,有创建到消亡的生命周期。可以比作是一次胶片放映的过程。一个程序可以被多个进程执行,一个进程也可以执行多个程序。
单道程序具有封闭性(所谓封闭性就是程序一旦运行,结果就只取决于程序本身,后面我们还会看到,[b]线程封闭可以作为一种线程安全的技巧应用到多线程中[/b]),顺序性和可再现性(可再现性指程序在同一数据集上执行结果总是一样的)。为了提高计算机系统内各种资源的使用效率,引入了多道程序设计,多道程序主要体现在(1)资源共享和(2)并发性上面,后面几篇我会不断强调就是因为这两个特性才可能导致线程不安全,破坏任意特性都可以保证多线程的安全性。多道程序不再具有封闭性和再现性。

进程通常由三部分组成,程序、数据集合和进程控制块(PCB, process control block)。Pcb是进程动态特性的集中表现,主要包含进程调度信息和现场信息,调度信息包括进程名,进程号,优先级等;现场信息主要包含程序状态字,时钟寄存器等。总之,每个进程都有自己独立的代码和数据空间,独立的程序计数器等上下文环境,进程切换的开销是比较大的。

操作系统依据进程控制块对进程控制和管理。
操作系统中往往设计一些能完成特定功能且不可中断的过程。这些不可中断的过程称为[b]原语[/b]。用于控制进程的原语有:
1)创建原语。为一个程序分配一个工作区和建立一个进程控制块,并置该进程为就绪状态。
2)撤销原语。一个进程完成工作后,收回它的工作区和进程控制块。
3)阻塞原语。进程运行过程中发生等待事件时,把进程状态改为等待态。
4)唤醒原语。当进程等待的事件发生时,把进程的状态改为就绪态。

创建一个进程大体分为以下几步:
1) 申请一个空白的PCB和唯一的进程号pid
2) 为新进程分配除CPU以外的资源,包括内存空间
3) 初始化PCB中的数据项
4) 将新进程的PCB插入系统的就绪队列
进程主要包括就绪,运行,阻塞三种状态,状态间可以转换:

[img]http://dl2.iteye.com/upload/attachment/0089/2551/083e1c1b-42da-38e7-8847-ffc301e1fe40.bmp[/img]


3.线程是进程内的一个执行单元,也是进程内的可调度实体。一个线程是进程内的一个顺序控制流。一个程序至少有一个进程,一个进程至少有一个线程。
1)地址空间:进程具有自己独立的地址空间,线程共享进程的地址空间
2)资源拥有:进程是资源分配的基本单位,线程共享进程的资源
3)线程是CPU调度的基本单位,进程不是
4)线程和进程均可并发执行。线程的创建,通信和切换的开销比进程小很多,由此产生了线程。
线程本身不能独立运行,必须运行在进程中,使用进程的地址空间,每个线程拥有自己独立的程序计数器。

[b]1.2 线程的创建[/b]
通常有三种方法创建线程(1)继承Thread类,重写run()方法。 (2)实现Runnable接口和run()方法,把实现体依附在Thread类上运行。(3)实现Callable接口,通过FutureTask依附在Thread上运行。后面后介绍后两者之间的区别。
这三种方法都是通过Thread类的start()方法启动的,自动执行run方法,显式的调用run()方法是不会启动一个线程的。
因为extends Thread实现线程会导致不能再继承其他类了,而implements Runnable还可以实现其他接口,所以一般都是采取实现Runnable接口(或Callable接口)来创建线程。步骤:
[b]step1:实现接口[/b]
class MyThread implements Runnable
{
public void run()
{
...
}
}


[b]step2:创建线程对象[/b]
MyThread runnable = new MyThread();


[b]step3:将Runnable对象关联到Thread[/b]
Thread thread = new Thread(runnable);


[b]step4:启动线程[/b]
thread.start();


Jdk5.0开始提供了线程池api,可以通过工厂类Executors创建ExecutorService类型的线程池,然后调用execute(Runnbale target)方法执行线程体,最后调用shutdown()方法结束线程调用,一般服务器都需要线程池,如web服务器,ftp服务器。

上述线程(池)的创建可以很方便的找到例子。

[b]1.3 线程的基本控制[/b]
线程创建后可以调用start启动,根据线程任务的特性和线程之间的协调性要求,需要对线程进行控制。通常是通过调用Thread对象的方法实现的。主要有sleep(), suspend(),resume(), join(), interrupt() 和stop(),一般情况下方法的调用会导致线程状态的切换。
注意:stop(), suspend(),resume()三个方法不推荐使用,推荐使用Object对象的wait/notify方法。
原因讨论可以参考:[url]http://xiaohuabiao.blog.163.com/blog/static/138482182008111605814290/[/url]

(1) Thread.sleep()方法使当前线程暂停一段指定的时间。中断(interrupt)可以终止睡眠时间。
(2) Join()方法会让一个线程等待另一个线程执行终止(含义是:wait for this thread to die)。比如在t1线程中调用t2.join(),则t1线程会等待t2线程结束才开始运行自己的方法。也可以像sleep方法一样指定等待的时间。同样这个等待也可以被中断。
(3) 使用中断interruput取消线程。已经启动的线程isAlive()方法返回true。有三种方法可以终止线程1)run方法正常返回 2)意外终止 3)应用程序终止。Interrupt可以在线程执行任务结束之前取消线程,其实不是真正的停止线程。调用这个方法时线程自己会检测线程状态,只是设置isInterrupted标志为true, 不会中止后面的代码。但如果是线程在调用wait,sleep等方法时调用interrupt()则会中断这个等待并抛出InterruptedException异常,程序员可以根据异常终止线程的处理。
还可以参考:[url]http://polaris.blog.51cto.com/1146394/372146[/url]
(4) stop方法会强迫线程停止,但方法本身是不安全的,比如线程中的对象处在不一致的状态下。该方法已经废弃了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值