一、sleep()和wait()
1.1sleep()
使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。 线程不会丢失任何显示器的所有权。
sleep方法属于Thread类中方法,表示让一个线程进入睡眠状态,等待一定的时间之后,自动醒来进入到可运行状态,不会马上进入运行状态,因为线程调度机制恢复线程的运行也需要时间,一个线程对象调用了sleep方法之后,并不会释放他所持有的所有对象锁,所以也就不会影响其他进程对象的运行。但在sleep的过程中过程中有可能被其他对象调用它的interrupt(),产生InterruptedException异常,如果你的程序不捕获这个异常,线程就会异常终止,进入TERMINATED状态,如果你的程序捕获了这个异常,那么程序就会继续执行catch语句块(可能还有finally语句块)以及以后的代码。
*注意 sleep()方法是一个静态方法,也就是说他只对当前对象有效,通过t.sleep()让t对象进入sleep,这样的做法是错误的,它只会是使当前线程被sleep 而不是t线程
1.2 wait()
wait()来自object类,一旦对象调用了该方法就必须采用notify()以及notifyall()用来唤醒该线程,如果线程拥有某个或某些对象的同步锁,在调用wait()后会释放该线程所持有的同步资源,而不限于这个调用了wait()的对象wait()也同样会在wait的过程中有可能被其他对象调用interrupt()方法而产生。
1.3区别
1.从出身来讲,sleep()来自Thread类 wait()来自Object类。
2.从功能特性来说,sleep()不会释放同步锁,wait()可以释放,使得其他线程可以继续使用同步控制块或方法。
3.从使用位置来说,sleep()可以使用在任何位置,wait()只能用在同步块或者同步方法中。
4.sleep()需要捕获,处理异常;wait()则不需要,可以直接使用。
二、volatile和synchronized
2.1 volatile
volatile是Java提供的轻量级同步机制,同步块(或方法)和 volatile 变量,相比于synchronized(synchronized通常称为重量级锁),volatile更轻量级,因为它不会引起线程上下文的切换和调度。但是volatile 变量的同步性较差(有时它更简单并且开销更低),而且其使用也更容易出错。
2.1.1 volatile的特性
(1)保证可见性,不保证原子性
a.当写一个volatile变量时,JMM会把该线程本地内存中的变量强制刷新到主内存中去;
b.这个写会操作会导致其他线程中的缓存无效。
(2)禁止指令重排
重排序是指编译器和处理器为了优化程序性能而对指令序列进行排序的一种手段。重排序需要遵守一定规则:
a.重排序操作不会对存在数据依赖关系的操作进行重排序。
比如:a=1;b=a; 这个指令序列,由于第二个操作依赖于第一个操作,所以在编译时和处理器运
行时这两个操作不会被重排序。
b.重排序是为了优化性能,但是不管怎么重排序,单线程下程序的执行结果不能被改变
2.2 synchronized
synchronized可作用于一段代码或方法,既可以保证可见性,又能够保证原子性。
可见性体现在:通过synchronized或者Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存中。
原子性表现在:要么不执行,要么执行到底。
Synchronized是Java并发编程中最常用的用于保证线程安全的方式,其使用相对也比
较简单。但是如果能够深入了解其原理,对监视器锁等底层知识有所了解,一方面可
以帮助我们正确的使用Synchronized关键字,另一方面也能够帮助我们更好的理解并
发编程机制,有助我们在不同的情况下选择更优的并发策略来完成任务。对平时遇到
的各种并发问题,也能够从容的应对。
2.3区别
1.从作用范围, volatile仅能使用在变量级别; synchronized则可以使用在变量、方法、和类级别的
2.从并发编程的角度, volatile仅能实现变量的修改可见性,并不能保证原子性;synchronized则可以保证变量的修改可见性和原子性
3.volatile不会造成线程的阻塞; synchronized可能会造成线程的阻塞。
4.volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化