线程的几种状态
Java语言定义了线程的五种状态:新建,运行,无限期等待,限期等待,阻塞,结束。
几种状态转换关系
阻塞状态和等待状态的区别:阻塞状态在等待获取到一个排它锁,这个事件将在另外一个线程放弃这个锁的时候发生,而等待状态则是在等待一段时间或者唤醒动态的发生,在程序等待进入同步区域的时候,线程将进入这种状态。
线程安全如何实现
1) 互斥同步
互斥是实现同步的一种手段,临界区,互斥量和信号量都是主要的互斥实现方式。在Java中最基本的互斥同步手段就是synchronized关键字。Synchronized同步块对同一个线程来说是可重入的,不会出现自己把自己锁死的情况。除了这个关键字之外,我们还可以使用java,util.,concurrent包中的重入锁ReentrantLock来实现同步,ReentrantLock增加一些高级功能,主要有:等待可中断,可实现公平锁,以及锁可以绑定多个条件。
等待可中断:当前持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情,可中断性对处理执行时间非常长的同步块很有帮助。
公平锁是指多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁,非公平锁不保证这一点。Synchronized中的锁是非公平的,ReentrantLock默认情况下也是非公平的,但是可以通过带布尔值的构造函数要求使用公平锁。
2) 非阻塞同步
互斥同步主要是进行线程阻塞和唤醒所带来的问题,从处理问题的方式来说,互斥同步属于一种悲观的并发策略,总是认为只要不去做正确的同步措施,就是出现问题。
这里介绍一下CAS(compare-and-Swap)比较并交换,这个指令需要有3个操作数,分别是内存位置,旧的预期值和新值。CAS指令执行时,当且仅当V符合旧的预期值A时,处理器用新值B更新V的值,否则他就不执行更新,但是无论是否更新了V值,都会返回V的旧值,上述的处理过程是一个原子操作。
3) 无同步方案
如果一个方法本来就不涉及共享数据,那他自然无需任何同步措施去保证正确性,因此会有一些代码天生就是线程安全的。
Java中实现多线程的方式
1)继承Thread类创建线程
2)实现Runnable接口
3) 实现Callable接口,通过FutureTask创建线程
4)Executors类,提供了一系列工厂方法用于创建线程池,返回的线程池都实现了ExecutorService接口。
public static ExecutorService newFixedThreadPool(int nThreads)
创建固定数目线程的线程池。
public static ExecutorService newCachedThreadPool()
创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
public static ExecutorService newSingleThreadExecutor()
创建一个单线程化的Executor。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
如果文章中有任何问题,欢迎指出~~~