Java基础——线程,锁机制

来源:互联网 发布:淘宝网和爱淘宝一样吗 编辑:程序博客网 时间:2024/06/01 20:03
------- android培训、java培训、期待与您交流! ----------

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

附加:安卓里面的线程:http://blog.csdn.net/u011216417/article/details/46011179

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方法            参考:http://blog.csdn.net/u011216417/article/details/45481929
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 可以花更少的时候来调度线程,把更多时间用在执行线程上。)。

好处:http://blog.csdn.net/fw0124/article/details/6672522

 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 实例实质上被绑定到一个锁上。要为特定 Lock 实例获得 Condition 实例,请使用其newCondition() 方法。



附加:

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

>>

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

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

>>

0 0
原创粉丝点击