一、线程创建方式有两种:继承Thread类和实现Runnable接口
1、继承Thread,需要重写run方法,因为Thread类中的run方法什么也没有做。如果想开启新线程,光创建线程对象是远远不够的,只有执行线程对象的start()方法,才能在栈中开启新线程,并执行run()方法。如果没有调用start()方法,仅仅只是使用ThreadDemo 调用run()方法,跟一般对象调用函数没有任何区别,不会开启新的线程。
public class ThreadDemo extends Thread{
public void run(){
//线程任务区
}
}
2、实现Runnable接口,只是创建了线程任务,但是还需要创建线程对象。在创建线程对象时把线程任务对象作为参数,然后调用线程对象的start()方法,才能开启线程,并调用线程任务的run()方法。
public class RunnableSub implements Runnable{
public void run(){
//线程任务区
}
}
二、线程的状态
线程阻塞状态(拥有CPU的执行资格,但是没有CPU的执行权)
|sleep()时间过、调用notify()/notifyAll()方法
|
线程状态创建-----------------------start()--------------------------- 线程运行中-----------wait()、sleep()-----------------------线程冻结状态(释放CPU的执行资格和执行权)
(拥有CPU执行资格和执行权)
|
|(调用stop()方法,此方法已经过时;或者线程任务已经执行完毕;使用标记)
线程销毁
三、wait()与sleep()的区别
相同点:都是可以是线程处于冻结状态
区别:1、wait()方法只能在同步代码块中使用,并且释放CPU的执行权和执行资格;sleep()方法,可以在同步代码块中使用,也可以在同步代码块外部使用,如果在同步代码块中使用,不会释放锁,会释放CPU的执行权和执行资格,等待时间已过,获取CPU的执行权后会继续执行。如果是在同步代码块外会释放CPU的执行资格和执行权。
2、wait()方法需要被notify()/notifyAll()方法唤醒;sleep()方法时间已过就会从冻结状态变为阻塞状态。
四、同步代码块与同步函数的区别(同步代码块的区分就是按照锁来区分的)
相同点:两个都是为了保证线程安全。
区别:同步代码块使用synchronized(同步锁){
//同步锁是任意类的对象,因为Object类中包含监视器的方法,所以所有的类都具有监视器的方法。
//要处理共享数据的代码
}
同步函数是在函数类型上,锁是当前类的对象(this)
public synchronized void setName(name){
this.name=name;
}
五、判断是否需要同步
1、是否包含共享数据(如果不包含共享数据,就不需要使用同步);
2、处理共享数据的代码是否有多条。
六、解决线程安全问题的步骤
1、首先判断是否需要同步;
2、run()方法中有循环;
七、线程模型
1、单一的生产者和消费者;
2、多生产者和多消费者;
八、线程组的概念
为了方便管理线程,如果线程都处于假死状态时,可以使用线程调用interrupt()方法,强制关闭线程,如果有多个,就需要多次调用此方法;如果多个线程都在同一个线程组中,就可以使用线程组调用interrupt()方法,就相当于多个线程都调用了interrupt()方法。
九、前台线程与守候线程的区别
直接创建的线程都是前台线程,需要等待线程运行结束,线程才会正常关闭;
前台线程可以通过调用方法,将前台线程转化为守候线程,如果前台线程都运行完毕,守候线程就会自动关闭(不管有没有运行完)。
十、线程的优先级
1-10级,数字越大优先级越高,默认优先级是5,主线程也是5
十一、join()方法,yelid()方法
如果在主线程中调用join()方法,主线程就会等待当前线程执行完毕以后,才会继续执行;
该方法与sleep()类似,只是不能由用户指定暂停多长时间,不会释放锁,在run()方法中使用Thread.yelid();
原文:http://www.cnblogs.com/leiandjing/p/7820180.html