线程的创建
第一种创建方法 :extends Thread(java.lang.Thread)
1.创建子类继承Thread,
2.重写Thread的run()方法,方法内实现此子线程要完成的功能
3.创建子类的对象
4.调用线程的start(),启动此线程,自动调用run()方法
说明:一个线程只能执行一次start()
Thread常用方法:
start():启动线程并执行run()方法
run():放置子线程要执行的代码
currentThread():静态方法,调取当前线程
getName():获取此线程的名字
setName():设置此线程的名字
yield():调用此方法的线程放弃CPU执行权
join():在A线程中调用B线程的join 方法,表示当执行到此方法,A线程停止执行,直到B线程执行完毕后才继续执行。
isAlive():判断当前线程是否存活
sleep(long l):显式的让当前线程睡眠l毫秒
第二种创建线程方式:implements Runnable
该方法更好,解决了单继承的局限性。如果多个线程操作同一资源,用实现的方式更适合处理。因为可以把同一个Runnable的实现类对象作为多个不同线程的构造器参数。
1.创建一个实现Runnable接口的实现类
2.实现接口的抽象方法run();
3.创建一个Runnable接口实现类的对象
4.将此对象作为形参传递给Thread类的构造器中,创建Thread的对象
5.调用start()方法启动线程
Thread t = new Thread(s);//s为Runnable接口的实现类对象;
t.start();
设置线程的优先级:
线程的调度方式:
时间片、抢占式 :高优先级抢占式,同优先级时间片
1.getPriority():返回线程优先级
2.setPriority(int newPriority):改变线程优先级
线程创建时继承父线程的优先级
MAX_PRIORITY:10
MIN_PRIORITY:1
NORM_PRIORITY: 5
解决线程的安全问题:线程同步
同步方式1:同步代码块
synchronized(同步监视器){
//需要被同步的代码(操作共享数据的代码)
}
同步监视器:锁。选择一个类的对象充当。获得同步监视器的线程执行大括号内的同步代码,所有运行该段代码的相关线程共用同一把锁。
关键字synchronized修饰某个对象,表示该对象在任一时刻只能被一个线程访问。
在线程创建采用实现的方式时,考虑同步的话,可以使用this来充当锁。因为多线程使用的是同一个实现类对象作为线程构造器参数。
但在继承的方式创建线程中,慎用this!因为继承的方式是通过new新线程的形式,没有一个统一的对象,可以使用Thread派生类本身。(类本身也是一个类,Class类。)
同步方式2:同步方法
将操作数据的方法声明为synchronized,即此方法为同步方法,能保证当某一线程执行此方法时,其他线程在外等待此线程执行完毕此方法。可以视作对同步代码块方式内操作共享数据代码的封装。
一个类中,非静态同步方法的锁默认是this;静态同步方法的锁默认是当前类本身(例子见解决懒汉式单例的线程安全)。
所以,含同步代码块的非静态方法锁可以设置为this,含有同步代码块的静态方法的锁可以是当前类本身。
懒汉式单例对象的线程安全问题:
Singleton.class返回的是一个Class类型的对象。
线程通信:
(Object方法)
wait():线程等待,放弃CPU和同步资源,被其他线程唤醒后继续执行
nodify():唤醒排队等待同步资源的线程中优先级最高的
nodifyAll():唤醒排队等待资源的所有线程
这三个方法只能在synchronized方法或者synchronized代码块中才能使用,否则java.lang.illegalMonitorStateException异常
死锁问题:
不同线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己所需要的资源,就像形成了线程的死锁。