标签:
四.多线程
多线程: 一个程序同时执行多个任务,每个任务就是一个线程
多进程和多线程的区别: 每个进程都有自己的一套变量,线程共享数据
例如:一个浏览器同时下载多个图片,一个web服务器要处理多个并发请求
如果一个任务比较耗时,建议用一个独立的线程
1.一个简单的线程
1)在一个实现了Runnable接口的类中的run方法里面写任务代码
public interface Runnable
{
void run();
}
public class MyRunnalbe implements Runnalbe
{
public void run(){
task code
}
}
2) 创建上面的类 Runnalbe r= new MyRunable();
3) 由Runnalbe创建一个Thread类
Thread t =new Thread(r);
4) 启动线程
t.start();
还有一种启动多线程的方法
public class MyThread extends Thread
{
pubic void run(){}
}
Tread t =new MyThread();
t.start();//这种方法已不再推荐 因为这种方式会为每个任务开启一个独立的线程,开销太大
2.中断线程
stop和suspend方法已经遭到启用
interrupt可以用来请求终止线程
获得当前线程 静态方法Thread.currentThread() ,调用isInterrupted()方法检测中断标致置位状态 如果线程被阻塞 (sleep或wait),中断状态无法被检测
线程将中断作为一个终止请求
静态方法interrupted()方法会清除该线程的中断状态
isInterrupted()判断是否是中断状态,但不做出改变
2.3线程有六种状态
new(新生)
Runnable(可运行)
Blocked (被阻塞)
Waiting(等待)
Timed Waiting (计时等待)
Terminated(被终止)
查看当前线程的状态调用getState()方法
2.3.1 新生
new之后 ,调用start之前
2.3.2 可运行状态
调用start之后
2.3.3阻塞状态和等待状态
当对象锁被其他线程持有,则该线程进入阻塞状态
当线程等待另一个线程通知调度器一个条件时,它自己进入等待状态
有几个方法有超时参数 ,调用它们导致线程计时等待,直到超时期满或者得到通知,结束这种状态
2.3.4被终止
当run方法的代码执行完毕,或者执行抛出异常时候
2.4线程的属性
线程的优先级
守护线程
线程组
处理未捕获异常的处理器
2.4.2 守护线程
可以使用方法t.SetDaemon(true);将线程变为守护线程
守护线程的唯一用途是为其他线程提供服务
2.4.4未捕获异常处理器
run方法不能抛出被检测异常,但也不需要catch,而是将异常传给未捕获异常的处理器
2.5线程同步
多个线程操作同一个数据,可能造成数据的讹误
java5.0后提供两种机制防止代码块受并发访问的影响 synchoonized关键字和2.5.1ReentraLock类
用ReentraLock类保护代码块
myLock.lock(); //一个ReentraLock类
try
{}
finally
{
myLock.unlock();
}
把解锁放在finnally中很重要.否则可能会让其他线程永远阻塞
使用条件对象 管理获得锁但却不能做有用工作的线程
例如从帐号转出钱,发现帐号没钱了,那么需要等待帐号其他线程转入钱以后再转出,这时候需要条件对象
用条件对象表示余额充足的条件. 一个锁对象可以有一个或多个条件对象 ,通过
newCondition 方法获得
Condition con = blankLock.newCondition()
当发现余额不足道时候,会调用con.await()方法,线程会阻塞
con.signalAll()方法会激活线程
当一个线程调用await方法时,他不能自己激活自己,需要其他线程调用singnalAll方法才可以激活,如果不能激活就进入了死锁
总结:
锁用来保护代码片段,任何时刻只能有一个线程执行这个代码块\
锁可以管理试图进入被保护的代码块的线程
锁可以有一个或多个相关的条件对象
每个条件对象管理已经进入代码块但还不能运行的线程
2.5.2 synchronized关键字
Lock和Condition 提供了高度的封锁控制,但大多数时候不需要那样的控制
如果用synchronized声明方法.那么对象锁保护整个方法,要执行该方法,就要获得对象锁 public synchronized void method()
{
method body
}
等同于
public void method(){
lock();
method body
unlock()
}
内部对象锁只有一个相关条件,wait方法添加线程到等待集 ,notify /notifyAll解除阻塞
wait和notify/notifyAll 相当于 Lock中的await和singal/singalAll
一般情况下既不使用synchronized也不使用Lock,而是使用java.util.concurrent包中的一种机制,他会处理所有的加锁
2.6使用监视器保证线程安全
monitor
监视器是一个只有私有域的类
每个监视器类对象都有一个相关锁
使用该锁对所有方法进行加锁
该锁可以有任意多个相关条件
2.7死锁
所有线程都发生阻塞的情况
2.8 读写锁
java.util.concurrent.locks包中有两个类 ReentranLock和ReentranReadWriteLock
后者是读写锁
读写锁的使用:
1)创建读写锁对象
private ReentranReadWriteLock rrw=new ReetranReadWriteLock();
2)抽取读锁和写锁
Lock readLock=rrw.readLock();
Lock writeLock= rrw.writeLock();
3)对所有访问者加锁
readLock.lock();
...
4)readLock.unlock();
对所有修改者加锁,类似上面
2.9阻塞队列
队列已满后,继续添加,或者队列已空,继续删除,这就造成了阻塞
如果用队列作为线程管理的工具,用到put和take方法
java.util.concurrent包下的
LinkedBlockingQueue
ArrayBlockingQueue
可以使用阻塞队列管理线程集
标签:
原文地址:http://www.cnblogs.com/chuanqimessi/p/4748824.html