Thread笔记

来源:互联网 发布:图片尺寸测量标注软件 编辑:程序博客网 时间:2024/05/19 17:24

线程可以处于以下4种状态之一:

1)新建(new):当线程被创建时,它只会短暂地处于这种状态,此时它已经分配了必需的系统资源,并执行了初始化。此刻线程已经有资格获得CPU时间了,之后调度器将把这个线程转变为运行状态或阻塞状态。

2)就绪(Runnable):在这种状态下,只要调度器把时间分分配给线程,线程就可以运行。也就是说,在任意时刻,线程可以运行也可以不运行。只要调度器能分配时间时间片给线程,它就可以运行,这不同于死亡和阻塞状态。

3)阻塞(blocked):线程能够运行,但有某个条件阻止它的运行。当线程处于阻塞状态时,调度器将忽略线程,不会分配给线程任何CPU时间。直到线程重新进入了就绪状态,它才有可能执行操作。

4)死亡(dead):处于死亡或终止状态的线程将不再是可调度的,并且再也不会得到CPU时间,它的任务已经结束,或不再是可运行的。任务死亡的通常方式是从run()方法返回,但是任务的线程还可以被中断。

任务进入阻塞状态,可能有以下原因:

1)通过调用sleep()使任务进入休眠状态,在这种情况下,任务在指定的时间内不会运行。

2)通过调用wait()使用线程挂起。直到线程得到notify()或notifyAll()消息(或者在java SE5的java.util.concurrent类库中等价的signal()或signalAll()消息),线程才会进入就绪状态。

3)任务在等等某个输入/输出完成。

4)任务试图在某个对象上调用其同步控制方法,但是对象锁不可用,因为另一个任务已经获取了这个锁。

1.yield()让步

yield();

      静态方法Thread.yield()的调用是对线程调度器(java线程机制的一部分,可以将CPU从一个线程转移给另一个线程)的一种建议,但是这只是一个建议,没有任何机制保证它一定会被采纳。 当调用yield()时,你也是在建议具有相同优先级的其他线程可以运行。大体上,对于任何重要的控制或在调整应用时,都不能依赖于yield(),实际上,yield()经常被误用。需要注意的是,在调用yield()方法的时候锁并没有被释放。

2.sleep()睡眠

sleep();
      影响任务行为的一种简单方法就是调用sleep(),这将使任务中止执行指定的时间。需要注意的是,在调用sleep()方法的时候锁并没有被释放。每调用Thread.sleep()后,任务都将睡眠(即阻塞),这使得线程调度器可以切换到另一个线程,进而驱动另一人任务。但是,顺序行为依赖于底层的线程机制, 这种机制在不同的操作系统之间是有差异的,因此,你不能依赖于它。如果你必须控制任务执行的顺序,那么最好使用同步控制,或者在某些情况下,压根不使用线程,但是要编写自己的协作例程,这些例程将会按照指定的顺序在互相之间传递控制权。

3.join()

join();

      一个线程可以在其他线程之上调用join()方法,其效果是等待一段时间直到第二个线程结束才继续执行。如果某个线程在另一个线程t上调用t.join(),此线程将挂起,直到目标线程t结束才恢复。

也可以在调用join()是传一个超时参数(单位可以是毫秒,或者毫秒和纳秒),这样如果目标线程在这段时间到期时还没有结束的话,join()方法总能返回。

在已经调用了sleep()方法,也可以调用interrupt()方法中断,将给线程设定一个标志,表明该线程已经被中断,中断会抛出异常。然而异常被捕获时将清理这个标志,所以在catch子句中,这个标志总是是假的。

public class Sleeper extends Thread{private long duration;public Sleeper(String name, long sleepTime){super(name);this.duration = sleepTime;}@Overridepublic void run() {try {Thread.sleep(duration);} catch (InterruptedException e) {System.err.println(getName() + " was interrupted. isInterrupted():" + isInterrupted());//务必有返回return;否则线程将继续执行System.out.println(getName() + " has awakened."),这样就达不到线程中断的效果了return ;}System.out.println(getName() + " has awakened.");}}

public class Joiner extends Thread{private Sleeper t;public Joiner(String name, Sleeper t){super(name);this.t = t;}public void run(){try {t.join();} catch (InterruptedException e) {System.err.println(getName() + " was interrupted.");}System.out.println(getName() + " join completed.");}}

public static void main(String[] args){Sleeper sleeper = new Sleeper("sleeper", 2000);Sleeper sl = new Sleeper("sl", 2000);sleeper.start();sl.start();Joiner joiner = new Joiner("joiner", sleeper);Joiner jo = new Joiner("jo", sl);joiner.start();jo.start();                //中断线程slsl.interrupt();}


java5在java.util.concurrent包下加了一些很有用的线程池类:

Executors.newFixedThreadPool(int nThreads);Executors.newCachedThreadPool();Executors.newSingleThreadExecutor();
1. newFixedThreadPool(int nThreads),可以定义固定数量的线程放在线程池中,如果当前有任务进来,但没可用的线程,任务会进入阻塞排队,等待有可用的线程。

2. newCachedThreadPool(),这个线程池没有定义线程的数量(其实,最大数量是:Integer.MAX_VALUE),有任务进来时,如果线程有可用的线程(在这种线程池的线程空闲时长为60秒,60秒后会被销毁)的情况下,则用可用的线程,如果没有可用的线程就创建 一个新线程来执行任务。

3. newSingleThreadExecutor(),这种情况下,线程池只创建 一个线程。

当然,这种创建线程池的方式,还可以传另一个参数:Thread threadFactory

Executors.newFixedThreadPool(int nThreads, ThreadFactory threadFactory)Executors.newCachedThreadPool(ThreadFactory threadFactory)Executors.newSingleThreadExecutor(ThreadFactory threadFactory)

其中参数Thread threadFactory,可以用来定制由Executors创建的线程的属性(如后台、优先级、名称)

public class DaemonFromFactory implements ThreadFactory{     public Thread newThread(Runnable r){               Thread t  = new Thread(r);                r.setDaemon(true);                return t;     }    }


...

0 0
原创粉丝点击