Synchronized
注意:1)同步一定要同步不变的东西,会变的锁不住,对象地址肯定不会变
2)遇到死锁时会自动解锁
同步方法:简单,效率低,可以同步成员方法和静态方法
public class AccountRunnable implements Runnable{
private Account account=new Account();
@Override
public void run() {
withdraw();
}
private synchronized void withdraw() {
if (account.getYuE() >= 400) {//600
try {
Thread.sleep(1);//出让CPU执行权
} catch (InterruptedException e) {
e.printStackTrace();
}
//取钱
account.withDraw(400);//200 -400 =-200
System.out.println(Thread.currentThread().getName() + "取钱成功,余额是:" + account.getYuE());
} else {
//余额不足通知用户 不能取钱
System.out.println(Thread.currentThread().getName() + "取钱失败,余额是:" + account.getYuE());
}
}
}
同步代码块:synchronized(this|类.class| 资源(成员属性)){ }
public class AccountRunnable implements Runnable{
private Account account=new Account();
@Override
public void run() {
synchronized (account){
if (account.getYuE() >= 400) {//600
try {
Thread.sleep(1);//出让CPU执行权
} catch (InterruptedException e) {
e.printStackTrace();
}
//取钱
account.withDraw(400);//200 -400 =-200
System.out.println(Thread.currentThread().getName() + "取钱成功,余额是:" + account.getYuE());
} else {
//余额不足通知用户 不能取钱
System.out.println(Thread.currentThread().getName() + "取钱失败,余额是:" + account.getYuE());
}
}
}
}
Lock重入锁
注意:1)使用重入锁时要先创建锁,Lock lock=new ReentrantLock();
2)需要我们自己手动上锁;(lock.lock())和手动开锁(lock.unLock()),当线程出现死锁时不会自动解锁,一定要手动解锁;
3)当需要两个及以上的锁时需要:Condition con1=lock.newCondition();
4)在lock.lock()和lock.unLock()当中使用con1.await()使得当前线程进入等待队列中,让出CPU,con1.signal()唤醒等待的线程
public class ProductFactory {
//定义集合 存储商品
ArrayList<String> list = new ArrayList<>();
//库存商品最大为10
int max = 10;
private Lock lock=new ReentrantLock();
Condition produceLock=lock.newCondition();
Condition consumerLock=lock.newCondition();
//生产商品
public void produce(String name) throws InterruptedException {
lock.lock();
try {
//当库存满不再添加
//此时是多条线程 循环的去校验 是否已满
while (list.size()==max){
produceLock.await();
}
//将商品添加到集合内
list.add(name);
//输出信息
System.out.println(Thread.currentThread().getName() + "生产了商品:" + name+"商品的库存是:"+list.size());
//通知消费者进行消费
consumerLock.signal();
} finally {
lock.unlock();
}
}
//消费商品
public void commu() throws InterruptedException {
lock.lock();
try {
//当没有商品时 进行等待
while (list.size() == 0) {
consumerLock.await();
}
//移除一个商品
String name = list.remove(0);
System.out.println(Thread.currentThread().getName() + "消费者消费了:" + name+"商品的库存是:"+list.size());
//通知生产者进行生产
produceLock.signal();
} finally {
lock.unlock();
}
}
}
Volatile关键词
一种轻量级的同步策略,当多个线程进行操作共享数据时,可以保证内存中的数据可见性,可以从CPU中直接拿到所要的数据,当对这个数据进行操作时,也会第一时间被保存到CPU当中。
package com.xxxx.thread;
public class Demo03 {
public static void main(String[] args) {
Street street=new Street();
new Thread(new Person(street)).start();
new Thread(new Car(street)).start();
}
}
class Street{
private volatile boolean flag=false;
// false 走
public void we(){
if(flag!=false){
}else{
System.out.println("人走.....");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag=true;
}
}
// true 走
public void ns(){
if(flag!=true){
}else{
System.out.println("车走.....");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag=false;
}
}
}
class Person implements Runnable{
private Street street;
public Person(Street street) {
this.street = street;
}
@Override
public void run() {
while (true){
street.we();
}
}
}
class Car implements Runnable{
private Street street;
public Car(Street street) {
this.street = street;
}
@Override
public void run() {
while (true){
street.ns();
}
}
}
}
ThreadLocal
是一个操作本地线程隔离的数据的工具类,它本身并不存储数据,真正存储数据的仍然是线程Thread对象本身,Thread对象内部有一个threadLocals用来作为本地数据。
每一个使用该变量的线程都获得该变量的副本,副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。
//
public class MybatisUtil {
private static SqlSessionFactory factory = null;
private static ThreadLocal<SqlSession> th = new ThreadLocal<>();
static {
try {
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
factory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获得session对象
public static SqlSession getSession() {
SqlSession sqlSession = th.get();
if (sqlSession == null) {
sqlSession = factory.openSession(true);
th.set(sqlSession);
}
return th.get();
}
//关闭session的操作
public static void closed() {
SqlSession sqlSession = th.get();
if (sqlSession != null) {
sqlSession.close();
}
th.set(null);
}
}