实现线程三种方式
java实现线程的方式总共有3中方式,一种是接口的形式,另一种是继承,还有一个中是接口的方式不过带有返回值,所以我们可以判断该线程是否成功
Runable
class judy implements Runnable{
@Override
public void run() {
}
}
有的人可能会问,start和run的区别是什么,start方法让线程进行就绪状态,等待cpu分配资源, start里面调用了run方法, 而run方法仅仅是一个简单方法,并没有启用一个新的线程, 但是start不一样,因为当他得到cpu的时候,他就会启动一个新的线程
Thread
class judy extends Thread{
@Override
public void run() {
super.run();
}
void test(){
System.out.println("test");
}
}
judy test = new judy();
test.start();
为什么有一个可以创建线程的方法,还会有一个,因为根据java的特性是单继承,所以我们还可以通过接口来创建线程
Callable
callable的主要作用就是可以获得该线程的返回值,然后根据返回值做处理
class judy implements Callable{
@Override
public Object call() throws Exception {
return null;
}
}
public static void main(String[] args){
Callable<String> callable = new judy();
FutureTask<String> futureTask = new FutureTask<String>(callable);
Thread thread = new Thread(futureTask);
thread.start();
futureTask.get();//获取线程返回值
}
}
Synchronized
线程同步,表示当多个线程同时使用的是一个对象的时候,sync只让一个运行,其他的必须等待
多个线程在同时运行的时候如果访问的不是不同对象那么他们就是线程安全的,否则就使用sync,来保证线程的同步运行
sync几种方式
1 class 锁
2 方法锁
3 代码块锁
class judye{
public synchronized Object call(){
return null;
}
}
执行大概步骤
- 获取锁
- 执行方法
- 释放锁
可重入
可重入的意思指的是一个线程再获得锁之后,可以调用其他同样锁的代码 , 为什么他可重入, 是因为他在底层判断你是否是当前线程, 如果是当前线程那么可以继续执行, 如果不是当前的线程那么不允许执行
内存可见性
由于sync的同步作用所以我们是原子性操作, 但是sync同时也具有内存可见性, 在释放锁的时候, 所有写入都会写回到内存, 在获得锁之后, 都会从内存中读取最新的数据
三大特性
1原子性:一步操作,例如int i = 5, 而i++则不是原子性,因为她分为3步
2有序性:可以理解sync,同步
3 可见性:volatile,工作区与内存可见,同步
ReentrantLock
1 他实现了Lock接口, lock接口是jdk1.5的时候出来的,他实现结果跟sync是一个道理,不过他是finally来释放锁的
sync是jvm层面,lock是类层面,sync锁状态不可以判断,Lock的锁状态可以判断,sync不可中断, lock可以中断也有公平锁
public class ReentrantLock implements Lock
2ReentrantLock 总共实现两种方式,公平锁和非公平锁
我们先来看非公平锁
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
//获取当前线程
final Thread current = Thread.currentThread();
//同步状态
int c = getState();
//线程可以进入,返回true
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//判断是否是当前线程
else if (current == getExclusiveOwnerThread()) {
//线程数加1
int nextc = c + acquires;
//抛出异常
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
//不是当前线程返回false
return false;
}
释放锁
protected final boolean tryRelease(int releases) {
//减去释放
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
//释放锁
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
//保存减去值的状态
setState(c);
return free;
}
具体内容可以看注释
公平锁
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
公平锁每次都是从同步队列中的第一个节点获取到锁,而非公平性锁则不一定,有可能刚释放锁的线程能再次获取到锁.,非公平锁肯能会导致解饿状态
Atomic
原子性
Wait和Notify
消息通知