线程及线程安全
一、线程概念
进程
可以看成是在计算机当中运行的一块代码。
线程
可以看成是在计算机当中运行的一小块代码。
CPU处理任务
1.在单位时间时间片上只能执行一个线程。
2.CPU看到内存中有很多的线程,CPU在单位时间片(时间片:很微小的时间单位)上高速切换线程执行。
线程的作用
1.可以将代码中(软件)的某些独立的功能包装起来,单独作为任务交给CPU处理。
2.将需做的某个功能封装成一个线程体,该线程可以独立的获得CPU分配的资源从而实现多功能同时运行。
进程与线程的关系
一个进程中可以有多个线程,至少得有一个线程;线程是进程中的最小单位;也可以把线程看成是一个轻量级的进程。
二、创建并启动线程的方式
继承线程父类方式
1.创建一个类继承Thread父类。
2.根据实际业务需求,重写父类的run方法。
3.在main方法中创建自定义类的对象,并执行start方法。
实现runnable接口方式
1.创建一个业务类实现runnable接口。
2.根据实际业务需求,重写run方法。
3.在main方法中创建Thread类的对象,将业务类对象作为参数传入,并执行该对象的start方法。
继承Thread 和实现Runnable的区别
1、继承有局限,Java中类只能够单继承。
2、实现的方式,我们的类在业务上可以继承它本应该有的类,同时可以实现接口变成一个线程类。
3、关于数据共享的问题:就看所谓被共享的数据所在的类的对象被创建了几个。
注意事项
直接调用run方法和start的区别
1.可以直接调用run方法,但是没有启动一个独立的线程。
2.只有调用start 才会启动一个独立的线程。
自己启动的线程和主线程的关系
1.直接写一个最简单的hello word 程序,就有一个主线程。
2.一个线程一旦启动就是独立的了,和创建启动它的环境没有直接的包含关系。
三、线程类
构造方法
1.Thread() //创建一个新的Thread对象
2.Thread(String name) //创建一个新的有指定线程名的 Thread对象
3.Thread(Runnable target) //将Runnable业务类对象作为参数,创建一个新的 Thread对象
4.Thread(Runnable target, String name) //将Runnable业务类对象作为参数,创建一个新的有指定线程名的 Thread对象
普通方法
1. static Thread currentThread() //返回对当前正在执行的线程对象的引用
2. String getName() //返回此线程的名称
3. void setName(String name) //设置线程对象的名字
4. void setPriority(int newPriority) //设置线程对象的优先级
5. int getPriority() /*获取线程的优先级
1-10,越大优先级越高,执行越早,越小就执行越晚
5是默认优先级。
当前线程的优先级与创建线程对象的环境的优先级一致*/
6. boolean isDaemon() /*判断这个线程是否是守护线程。 GC是守护线程
一个线程的默认状态和创建它的环境线程状态一致 */
7. void setDaemon(boolean on) /*将当前线程设置为守护线程
活跃的线程不能设置为守护线程*/
8. void join() //等待join线程执行完后,再执行当前线程
9. void join(long millis)//等待join线程线程死亡最多 millis毫秒
10. static void sleep(long millis) //阻塞当前线程指定的毫秒数后再执行
//一般用来模拟网络延迟,可以做计时器,还可以做倒计时
11. void interrupt() //中断这个线程。 在多线程中常用
12. static boolean interrupted() //测试当前线程是否中断。 在多线程中常用
13. boolean isAlive() //测试这个线程是否活着
14. Thread.State getState() //返回此线程的状态
15. long getId() //返回此线程的标识符
四、线程同步
作用
代码执行到一个位置之后,如果切换到另一个线程,在切换回来,那么会从刚才切换走的代码位置继续执行:产生线程安全问题,造成数据的错乱,因此需要线程同步来解决这样的问题
方式
悲观锁
代码块
语法结构
synchronized (同步监听对象) {
可能引发线程安全问题的代码
}
特点
1.上面的同步监听对象可以是任意的对象
2.保证所有的线程共享一个同步监听对象;也就是保证被同步监听对象是被所有线程共享的
3.常用的方式:使用类的字节码对象 XXX.class
同步方法
语法结构
在需要被同步的方法上面加关键字 synchronized
特点
1.如果是一个非static的方法,那么同步监听对象就是this
2.如果是static修饰的方法,那么同步监听对象就是当前方法所在的类的字节码对象
乐观锁
使用方式
1.ReentrantLock() 创建一个 ReentrantLock的实例(ReentrantLock(boolean fair) 根据给定的公平政策创建一个 ReentrantLock的实例。理论上获取锁的几率是相同的)
2.在即将执行有线程安全问题的代码前使用lock方法加锁
3.使用try-finally结构,try中执行有线程安全问题的代码,finally中释放锁
注意事项
1. 使用选择:
锁机制效率高且功能更加强大,建议使用.
同步方法简单,如果能够满足性能要求建议使用同步方法。
2. 同步对象:必须保证几个线程对象共享的是同一个同步对象(一般使用当前类的字节码文件或者this)。
3. 锁原则:最小范围原则,为了保证执行效率。