Java马士兵高并发编程视频学习笔记(二)

时间:2022-09-20 08:43:35

1.ReentrantLock的简单使用  

Reentrant n.再进入

ReentrantLock 一个可重入互斥Lock具有与使用synchronized方法和语句访问的隐式监视锁相同的基本行为和语义,但具有扩展功能。(从jdk1.8中文版复制而来)

可以完成synchronized相同的作用,但必须手动释放锁

package com.dingyu2;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Reentrant n.再进入
 * ReentrantLock 一个可重入互斥Lock具有与使用synchronized方法和语句访问的隐式监视锁相同的基本行为和语义,但具有扩展功能。(从jdk1.8中文版复制而来)
 * 可以完成synchronized相同的作用,但必须手动释放锁
 * @author dingyu
 *
 */
public class ReentrantLock1 {
    private Lock lock = new ReentrantLock();

    public void m1() {
        try {
            lock.lock();//synchronized(this)类似,锁定的是堆的对象
            for (int i = 0; i < 10; i++)
                System.out.println("m1-" + i);
        } catch (Exception e) {
            System.out.println("m1启动");

        } finally {
            System.out.println("m1结束");
            lock.unlock();
        }
    }

    public void m2() {
        try {
            lock.lock();
            for (int i = 0; i < 10; i++)
                System.out.println("m2-" + i);

        } catch (Exception e) {
            System.out.println("m2启动");

        } finally {
            System.out.println("m2结束");
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ReentrantLock1 reentrantLock1 = new ReentrantLock1();
        new Thread(() -> reentrantLock1.m1()).start();
        new Thread(() -> reentrantLock1.m2()).start();
    }
}

2.ReentrantLock对synchronized的扩展之tryLock()

package com.dingyu2;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * ReentrantLock对synchronized的扩展之tryLock()
 * 
 * @author dingyu
 *
 */
public class ReentrantLock2 {
    private Lock lock = new ReentrantLock();

    public void m1() {
        lock.lock();// 一直锁着,不手动释放, 和synchronized(this)类似,锁定的是堆的对象
    }

    public void m2() {
        boolean isNotLock = lock.tryLock();// 如果别的进程锁着就返回false,如果没锁返回true
        // 我们可以根据有没有锁来执行自己的逻辑,而不需要等着锁的释放,更加灵活
        if (isNotLock) {
            System.out.println("lock对象没有被锁定");
        } else {
            System.out.println("lock对象被锁定了");
        }
    }

    public static void main(String[] args) {
        ReentrantLock2 reentrantLock2 = new ReentrantLock2();
        new Thread(() -> reentrantLock2.m1()).start();
        new Thread(() -> reentrantLock2.m2()).start();
    }
}

3.ReentranLock对synchronized的扩展:可以被另外的线程打断

package com.dingyu2;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * ReentranLock对synchronized的扩展:可以被另外的线程打断
 * 因为m1方法一直占着锁,m2永远不可能得到锁,既然得不到锁,我们就关闭m2好了,这时候得用lockInterruptibly
 * 
 * @author dingyu
 *
 */
public class ReentrantLock3 {
    private Lock lock = new ReentrantLock();

    public void m1() {
        lock.lock();
        try {
            System.out.println("t1 start");
            while (true) {
            }
        } finally {
            lock.unlock();
            System.out.println("t1 end");
        }
    }

    public void m2() {
        try {
            lock.lockInterruptibly();
            System.out.println("t2 start");
        } catch (InterruptedException e) {
            System.out.println("t2被打断了");
        } finally {
            if (lock.tryLock())
                lock.unlock();
            System.out.println("t2 end");
        }
    }

    public static void main(String[] args) {
        ReentrantLock3 reentrantLock3 = new ReentrantLock3();
        Thread t1 = new Thread(() -> reentrantLock3.m1(), "t1");
        t1.start();
        Thread t2 = new Thread(() -> reentrantLock3.m2(), "t2");
        t2.start();
        t2.interrupt();
    }
}

4.ReentrantLock对synchronized的扩展 : 可以指定公平锁

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * ReentrantLock对synchronized的扩展 : 可以指定公平锁,哪个线程等待时间长,哪个先执行
 * 在构造函数中放入ture参数
 * 
 * @author dingyu
 *
 */
public class ReentrantLock4 {
    private Lock lock = new ReentrantLock(true);

    public void m1() {
        for (int i = 0; i < 10; i++) {
            try {
                lock.lock();
                System.out.println(Thread.currentThread().getName() + "running");
            } finally {
                lock.unlock();
            }
        }
    }
    
    public static void main(String[] args) {
        ReentrantLock4 lock4 = new ReentrantLock4();
        new Thread(()->lock4.m1(),"t1").start();
        new Thread(()->lock4.m1(),"t2").start();
    }
}

5.使用wait和notifyAll实现消费者生产者模式

package com.dingyu2;

import java.util.LinkedList;

/**
 * 使用wait和notifyAll实现消费者生产者模式
 * 
 * @author dingyu
 *
 */
public class ProduceConsumer {
    private final LinkedList<Integer> lists = new LinkedList<Integer>();
    private final int MAX = 10;
    private int count = 0;

    public synchronized void put(Integer i) {
        while (lists.size() == MAX) { // wait大多数情况和while一起用
            try {
                this.wait();// 如果满了我就释放锁,并且等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        lists.add(i);// 生产一个
        count++;
        this.notifyAll();// 叫醒消费者可以消费啦
    }

    public synchronized Integer get() {
        while (lists.size() == 0) {
            try {
                this.wait();// 如果集合为空,不能消费,释放锁,等着
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Integer num = lists.removeFirst();
        count--;
        this.notifyAll();// 叫醒生产者,可以继续生产啦
        return num;
    }

}

6.使用Condition 完成生产者消费者模式

package com.dingyu2;
/**
 * 使用Condition 完成生产者消费者模式
 * @author dingyu
 *
 */

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ProduceConsumer2 {
    private final LinkedList<Integer> lists = new LinkedList<Integer>();
    private final int MAX = 10;
    private int count = 0;

    private Lock lock = new ReentrantLock();
    private Condition p = lock.newCondition();// 生产者
    private Condition c = lock.newCondition();// 消费者

    public void put(Integer i) {
        try {
            lock.lock();
            while (lists.size() == MAX) {
                try {
                    p.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            lists.add(i);
            count++;
            c.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public Integer get() {
        Integer i = null;
        try {
            lock.lock();
            while (lists.size() == 0) {
                try {
                    c.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            i = lists.removeFirst();
            count++;
            p.signalAll();
        } finally {
            lock.unlock();
        }
        return i;
    }

}

 7.ThreadLocal 线程局部变量  每个线程中的这个变量归自己线程管

package com.dingyu;

public class ThreadLocal1 {
    private ThreadLocal<Integer> tl = new ThreadLocal<Integer>();

    public void m1() {
        System.out.println(tl.get());
    }

    public void m2() {
        tl.set(7898);
    }

    public static void main(String[] args) {
        ThreadLocal1 local1 = new ThreadLocal1();
        new Thread(() -> local1.m2()).start();

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(() -> local1.m1()).start();
    }
}