黑马程序员——多线程

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------

线程,指的是在程序执行过程中沿一条线索逐条语句按顺序执行的流程。main函数就是一个线程,叫做主线程。在多线程开发过程中,随着主函数的进行,可以随时开启一个独立执行的线程。多线程可同时执行,同时执行的本质可以是CPU多核同时执行多个任务,也可以是CPU内核在多任务间的飞速切换。在Java中,线程被预定义包装成了java类库中的类,该类是java.lang.Thread,Thread实现Runnable接口(run()方法),当线程启动时,执行的就是run()方法。

线程类必须是Thread类或其子类。run()方法中的内容,是自定义线程类最核心的内容,可以在继承自Thread的类中重写run()方法,也可以通过定制一个实现了Runnable接口的类(实现其run()方法),再通过在Thread构造方法中传入一个该类对象的方式建立自定义线程。

线程的状态:

在Java当中,线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。 
  第一是创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。 
  第二是就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。 
  第三是运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。 
  第四是阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。 
  第五是死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪。 

并发编程引发的问题是不确定的,有可能在程序检测时并未发生,在客户使用的过程中却出现。Java使用并发系统会共享诸如内存和I/O这样的资源,因此编写多线程程序最基本的困难在于在协调不同线程驱动的任务之间对这些资源的使用,以使得这些资源不会同时被多个任务访问。
并发需要付出代价,包含复杂性代价,但是这些代价与程序设计、资源负载均衡以及用户使用方便方面的改进相比,就显得微不足道了。

Executor:
Java SE5对java.util.concurren包中的执行器(Executor)能管理Thread对象,简化编程。
将Runnable类对象作为参数传入Executor对象的execute(Runnable r)方法可以启动新的线程执行此Runnable中的run()方法。

ExectorService  exec=Executors.newCachedThreadPool();
ExectorService  exec=Executors.newFixedThreadPool();
ExectorService  exec=Executors.newSingleThreadExecutor();
exec.execute(r);

将Callable类(具有返回值的泛型类,其call()方法相当于Runnable类的run()方法,能产生线程;Callable<T>的返回值是T类对象。)对象作为参数传入ExecutorService(Executor子类)对象的submit(Callable<T>  c)方法,submit()方法可以在该Callable<T>的call()方法执行完毕时返回一个Future<T>类型对象。Future<T>对象的get()方法能获得T值,但该get()方法是一个阻塞式方法,只有在call()方法执行完毕时get()才返回值,Future<T>的isDone()方法可以用来判断Callable<T>的call()方法是否已经执行完毕并返回值。

Callable<T>  c=new Callable<T>(){
public T call(){
.....
return (T)t;
}
};
Future<T> fu=exec.submit(c);
if(fu.isDone)
T t=fu.get();
优先级:
优先级的高低决定了各线程执行频率的高低,而不是决定各线程的执行顺序。Thread的getPriority()和setPriority()方法可以用来获取和设置线程的优先级,但在大多数时间里,

所有线程都应该以默认的优先级运行,试图操纵线程优先级通过是种错误。JDK有10个优先级。

让步:
Thread的yield()方法会给线程调度器一个暗示:本线程的工作可以暂停一下了,让别的线程继续执行。但这只是一种暗示,没有任何机制保证它一定被线程调度器采纳。

后台线程:
当所有非后台线程执行结束后,程序会自动终止所有未执行完毕的后台程序。Thread的setDaemon(boolean b)和isDaemon()可以用来设置和判断线程的后台性。
由后台线程创建的线程自动被设置成后台线程。
后台线程在被迫终止时,其中的finally子句不会得到执行。

 
线程中断:A、B为线程,在A中调用B.join();将使A线程中断,直到B线程执行完毕。在线程内部调用Thread.sleep(int n)将使该线程睡眠中断n毫秒,在线程内部调用Thread.wait(),将使该线程进程等待状态,直到被唤醒(notify()方法),当A线程处于中断状态的任意一种状态时,B线程调用了A.interrupt()方法,A的中断状态将被消除,同时A中抛出InterruptedException。 
线程同步:为解决多线程间共享资源的问题,可以使用synchronized方法和代码块。返回值前标注synchronized的方法是同步的,其锁是该方法的对象(this),同一个对象的所有同步方法用的都是该对象本身,这些方法是同步的;同步代码块需指出作为锁的对象: 
synchronized(obj)//obj是锁
{
    .....
    代码块
    .....
}
使用同一个对象作为锁的同步代码块之间也是同步的。
Lock类:
Java SE5 java.util.concurrent类中的locks包中有Lock接口。该类具有实现类ReentrantLock,Lock类对象调用lock()和unlock()方法标记同步代码块的开始和结束,即锁定和解锁。通常将解锁放在try—finally的finally子句中。
Condition类:
可以通过在Condition上调用await()挂起一个任务,当外部条件变化后,可以通过调用signal()方法重新唤醒这个任务。Condition对象通过ReentrantLock的newCondition()方法获得,并且await()和signal()方法要位于该Lock对象的锁定范围内。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值