博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java基础——线程,锁机制
阅读量:4291 次
发布时间:2019-05-27

本文共 4308 字,大约阅读时间需要 14 分钟。

------- 、、期待与您交流! ----------

关于什么是线程,计算机系统的任务发展史,咱这里就不说了。说点比较有意思的东西。

附加:安卓里面的线程:

1.创建线程

使用Thread类和使用Runnable接口。在使用Runnable接口时需要建立一个Thread实例。因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例。

(方法一)Thread构造函数:

public Thread( );

public Thread(Runnable target);
public Thread(String name);
public Thread(Runnable target, String name);
public Thread(ThreadGroup group, Runnable target);
public Thread(ThreadGroup group, String name);
public Thread(ThreadGroup group, Runnable target, String name);
public Thread(ThreadGroup group, Runnable target, String name, long stackSize);

创建Thread类的时候,同时也要覆盖run方法,这样才有真正的执行体。
然后,再thread.start();,开启这个线程。

(方法二)使用Runnable接口

实现这个接口,也就是覆写接口里面的run方法。。实际上,实用实现接口的方法来创建线程,只是用这个实现接口的类去创建Thread类,然后,还是thread.start();。

(方法三)使用ExecutorService、Callable、Future实现有返回结果的多线程

2.线程的生命周期

生命周期这个东西,在作为一个服务在操作系统中,好像是经常出现的。android中,一个service有生命周期,一个Intent也有生命周期。

所谓的生命周期,其实可以看待成,任何的一个个体对象,在使用的任何时候都会有一些相应的动作。这个动作,可能是对象本身的,但是,居多,都是外界环境赋予的。编程的时候,我们只要重写这个方法,就可以被使用。

// 开始线程

public void start( );
public void run( );

// 挂起和唤醒线程

public void resume( ); // 不建议使用
public void suspend( ); // 不建议使用
publicstatic void sleep(long millis);//区别与class类中的wait方法            参考:
publicstatic void sleep(long millis, int nanos);
// 终止线程
public void stop( ); // 不建议使用
public void interrupt( );
// 得到线程状态
public boolean isAlive( );
public boolean isInterrupted( );
public static boolean interrupted( );
// join方法
public void join( ) throws InterruptedException;

Java线程具有五中基本状态

新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;
运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就 绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;
阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:
1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;
2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

3.多线程安全问题(锁机制,等待唤醒机制)

问题原因:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没执行完,另一个线程参与进来执行,导致共享数据的错误。

1、synchronized(同步的)

修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。 原子性(atomicity)和 可见性(visibility)

一个对象只有一个锁。同步函数锁是this, 静态同步函数锁是class

使用:1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法

2. synchronized 块:通过 synchronized关键字来声明synchronized 块。

关于线程的同步:

1. 在需要同步的方法的方法签名中加入synchronized关键字。
2. 使用synchronized块对需要进行同步的代码段进行同步。
3. 使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象。

4、对于同步的方法或者代码块来说,必须获得对象锁才能够进入同步方法或者代码块进行操作;

5、如果采用method级别的同步,则对象锁即为method所在的对象,如果是静态方法,对象锁即指method所在的Class对象(唯一);
6、对于代码块,对象锁即指synchronized(abc)中的abc;

功能限制,也是为什么有之后同步机制的原因:

它无法中断一个正在等候获得锁的线程,也无法通过投票得到锁,如果不想等下去,也就没法得到锁

2、ReentrantLock(入锁)是一种递归无阻塞的同步机制

java.util.concurrent.lock 中的Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现。这就为Lock 的多种实现留下了空间,各种实现可能有不同的调度算法、性能特性或者锁定语义。

ReentrantLock 类实现了Lock ,它拥有与synchronized 相同的并发性和内存语义,但是添加了类似锁投票定时锁等候可中断锁等候的一些特性。此外,它还提供了在激烈争用情况下更佳的性能。(换句话说,当许多线程都想访问共享资源时,JVM 可以花更少的时候来调度线程,把更多时间用在执行线程上。)。

好处:

 Lock 和 synchronized 有一点明显的区别 —— lock 必须在 finally 块中释放。

除此之外,与目前的 synchronized 实现相比,争用下的 ReentrantLock 实现更具可伸缩性。(在未来的 JVM 版本中,synchronized 的争用性能很有可能会获得提高。)这意味着当许多线程都在争用同一个锁时,使用 ReentrantLock 的总体开支通常要比 synchronized 少得多。

3、读写锁ReadWriteLock

读写锁比起mutex具有更高的适用性,具有更高的并行性,可以有多个线程同时占用读模式的读写锁,但是只能有一个线程占用写模式的读写锁,读写锁的三种状态:
1.当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞
2.当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是以写模式对它进行加锁的线程将会被阻塞
3.当读写锁在读模式的锁状态时,如果有另外的线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁的请求,这样可以避免读模式锁长期占用,而等待的写模式锁请求则长期阻塞。
读写锁最适用于对数据结构的读操作次数多于写操作的场合,因为,读模式锁定时可以共享,而写模式锁定时只能某个线程独占资源,因而,读写锁也可以叫做个共享-独占锁。

4、线程间通信Condition——

condition条件(也称为条件队列 或条件变量)是锁的一个实例,他可以与ReentrantLock结合使用,取代jdk自行操作的synchronize,自己控制锁的条件。Condition的强大之处在于它可以为多个线程间建立不同的Condition。

Condition可以替代传统的线程间通信,await()替换wait(),用signal()替换notify(),用signalAll()替换notifyAll()。

Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。

Condition 实例实质上被绑定到一个锁上。要为特定  实例获得 Condition 实例,请使用其 方法。

附加:

>>很多比较新的技术,都在java.util.concurrent中。针对于并发的线程处理,Java有一个包的类和方法,里面有很多不错的东西。

>>

>>多线程的处理,是一个永远的话题。在代码优化、产品优化的时候,是少不了的。

>>所以,,以后,,还要专门研究这个东西

>>

你可能感兴趣的文章
搭建秒杀环境:Docker + Nodejs + Kafka + Redis + MySQL
查看>>
如何使用 Lucene 做网站高亮搜索功能?
查看>>
java实用工具Google Guava,谷歌出品必是精品
查看>>
史上最全Spring面试71题与答案
查看>>
奔驰在打造未来汽车时的 DevOps 实践
查看>>
spring cloud eureka服务发现(高可用)
查看>>
spring cloud教程之使用spring boot创建一个应用 《7天学会spring cloud》
查看>>
分布式数据层中间件详解:如何实现分库分表+动态数据源+读写分离
查看>>
分布式数据层中间件详解:如何实现分库分表+动态数据源+读写分离
查看>>
Java中创建对象的5种方式
查看>>
SpringBoot 全局日期格式化(基于注解)
查看>>
spring mvc的跨域解决方案
查看>>
这些顶级的java开发技巧你都会了吗
查看>>
夯实基础:Java 动态代理及 RPC 框架简介
查看>>
深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接
查看>>
如何在子线程和线程池中使用 ThreadLocal 传输上下文
查看>>
Spring中@Async
查看>>
高并发架构系列:如何从0到1设计一个类Dubbo的RPC框架
查看>>
从 0 开始手写实现一个 RPC 框架
查看>>
Java程序员笔记,Spring构造器注入原理细节分析
查看>>