/**
* juc java.util.concurrent 工具包的简称 处理线程的工具包
*
* 线程状态
* NEW 新建
* RUNNABLE 准备就绪
* BLOCKED 阻塞
* WAITING 等待
* TIMED_WAITING 等待
* TERMINATED 结束
*
* wait与sleep
* 不同:
* wait是Object中的方法,会释放锁,但调用的前提是当前线程占有锁(代码要在synchronized中)
* sleep是Thread中的静态方法,sleep不会释放锁,也不占用锁
*
* 相同:
* 都可以被interrupted打断,并且从哪里睡着,就从哪里醒 官方建议在while里写睡眠,否则会造成虚假唤醒
*
* 串行与并行 并发与并行
*
* 并发:多项线程同时访问同一资源,
* 并行:多项工作一起进行,最后进行汇总
*
* 管程(Monitor:监视器 -> 锁) 在同一时间只有一个线程对资源进行访问,其他线程不能访问
*
*
* 用户线程与守护线程
* 用户线程:自定义线程,用户线程不结束,jvm不退出
* 守护线程:gc() 守护线程不结束,用户线程结束,jvm退出
*
* 线程的基本用法:
* 设置一个资源类,资源类中定义锁,定义操作对象,定义操作方法
* 不同的线程对该资源类进行访问,按照资源类中定义的规则对资源进行操作
*
*/
public class FirstDemo{
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + ":" + Thread.currentThread().isDaemon());
while (true) {
}
}, "aa");
thread.setDaemon(true);//将用户线程设置为守护线程
thread.start();
System.out.println(Thread.currentThread().getName()+"isOver");
}
}
/**
* Synchronized
*
* synchronized 同步锁
* 可以修饰代码块,方法,静态方法,类
* 在发生异常时,会自动释放锁
*/
public class SynchronizedDemo {
public static void main(String[] args) {
tiket tiket = new tiket();
new Thread(()->{
for (int i = 0; i < 40; i++) {
tiket.sale();
}
},"a").start();
new Thread(()-> {
for (int i = 0; i < 40; i++) {
tiket.sale();
}
},"b").start();
new Thread(()-> {
for (int i = 0; i < 40; i++) {
tiket.sale();
}
},"c").start();
}
}
class tiket{
private int num = 30;
public synchronized void sale(){
if(num>0){
System.out.println(Thread.currentThread().getName()+":"+(num--) +"剩余:"+num);
}
}
}
/**
* Lock 的使用方法
* 发生异常的时候不会主动释放锁,所以需要再try finnaly 中释放锁
* ReetrantLock 可重入锁 实现Lock接口,并对Lock接口进行序列化
* Condition 通过ReetrantLock 进行创建,对线程进行休眠(await()),唤醒(signal())等操作
* 通过创建多个Condition 可以对线程进行指向性唤醒(signal())操作,从而实现定制化线程
*/
public class LockDemo {
public static void main(String[] args) {
Ltiket ltiket = new Ltiket();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ltiket.sale();
}
},"a").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ltiket.sale();
}
},"a").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ltiket.sale();
}
},"a").start();
}
}
class Ltiket{
private int num = 30;
private final ReentrantLock lock = new ReentrantLock(); //可重入锁
public void sale(){
try{
lock.lock();
if(num>0){
System.out.println(Thread.currentThread().getName()+":"+(num--)+"剩余"+num);
}
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
/**
* 线程之间的通信
*/
public class ThreadDemo {
public static void main(String[] args){
share share = new share();
new Thread(()->{
for (int i = 0; i < 40; i++) {
try {
share.add();
} catch (Exception e) {
e.printStackTrace();
}
}
},"a").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
try {
share.decre();
} catch (Exception e) {
e.printStackTrace();
}
}
},"b").start();
}
}
class share {
private int num = 0;
public synchronized void add() throws Exception {
if (num != 0) {
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName() + "::" + num);
this.notifyAll();
}
public synchronized void decre() throws Exception{
if(num != 1){
this.wait();
}
num--;
System.out.println(Thread.currentThread().getName()+"::"+num);
this.notifyAll();
}
}
/**
* 虚假唤醒
* wait() notify()
* 官方建议将wait写进while循环中,防止醒来判断不生效
*/
public class ThreadDemo {
public static void main(String[] args){
share share = new share();
new Thread(()->{
for (int i = 0; i < 40; i++) {
try {
share.add();
} catch (Exception e) {
e.printStackTrace();
}
}
},"a").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
try {
share.add();
} catch (Exception e) {
e.printStackTrace();
}
}
},"c").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
try {
share.decre();
} catch (Exception e) {
e.printStackTrace();
}
}
},"b").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
try {
share.decre();
} catch (Exception e) {
e.printStackTrace();
}
}
},"d").start();
}
}
class share {
private int num = 0;
public synchronized void add() throws Exception {
// if (num != 0) {
// this.wait();//在哪里睡,就会在哪里醒 判断就没有生效 解决方案,写进while循环中
// }
while (num != 0){
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName() + "::" + num);
this.notifyAll();
}
public synchronized void decre() throws Exception{
// if(num != 1){
// this.wait();
// }
while (num != 1){
this.wait();
}
num--;
System.out.println(Thread.currentThread().getName()+"::"+num);
this.notifyAll();
}
}
/**
* 使用Lock 实现线程通信
* 加锁,解锁,睡眠,唤醒
*/
public class ThreadDemo1 {
public static void main(String[] args) {
Hello hello = new Hello();
new Thread(() -> {
for (int i = 0; i < 40; i++) {
hello.add();
}
}, "a").start();
new Thread(() -> {
for (int i = 0; i < 40; i++) {
hello.add();
}
}, "b").start();
new Thread(() -> {
for (int i = 0; i < 40; i++) {
hello.deAdd();
}
}, "c").start();
new Thread(() -> {
for (int i = 0; i < 40; i++) {
hello.deAdd();
}
}, "d").start();
}
}
class Hello {
private int num = 0;
private final ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void add() {
lock.lock();
try {
while (num != 0) {
condition.await();
}
num++;
System.out.println(Thread.currentThread().getName() + "::" + num);
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void deAdd() {
lock.lock();
try {
while (num != 1) {
condition.await();
}
num--;
System.out.println(Thread.currentThread().getName() + "::" + num);
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
/**
* 定制化线程
* <p>
* 让线程按照规定执行
*/
public class ThreadDemo2 {
public static void main(String[] args) {
shareResource shareResource = new shareResource();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
shareResource.print5(i);
}
}, "a").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
shareResource.print10(i);
}
}, "b").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
shareResource.print15(i);
}
}, "c").start();
}
}
class shareResource {
private int flag = 1;
private final ReentrantLock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
public void print5(int loop) {
lock.lock();
try {
while (flag != 1) {
condition1.await();
}
for (int i = 0; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + "::" + i + "第" + loop + "轮");
}
flag = 2;
condition2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void print10(int loop) {
lock.lock();
try {
while (flag != 2) {
condition2.await();
}
for (int i = 0; i <= 10; i++) {
System.out.println(Thread.currentThread().getName() + "::" + i + "第" + loop + "轮");
}
flag = 3;
condition3.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void print15(int loop) {
lock.lock();
try {
while (flag != 3) {
condition3.await();
}
for (int i = 0; i <= 15; i++) {
System.out.println(Thread.currentThread().getName() + "::" + i + "第" + loop + "轮");
}
flag = 1;
condition1.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
/**
* 集合的线程安全问题例子
*
*/
public class ExceptionDemo {
public static void main(String[] args) {
// List<String> list = new ArrayList();
//比较古老的解决方案
// List<String> list = new Vector<>();
// List<Object> list = Collections.synchronizedList(new ArrayList<>());
//juc 提供的解决方案
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();//写时复制
for (int i = 0; i < 30; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,8));
// System.out.println(list);
},String.valueOf(i)).start();
}
Set<String> set = new HashSet<>(); //解决方案 CopyOnWriteArraySet()
for (int i = 0; i < 30 ; i++) {
new Thread(()->{
set.add(UUID.randomUUID().toString().substring(0,8));
// System.out.println(set);
},String.valueOf(i)).start();
}
Map<String,String> map = new HashMap<>();//解决方案,ConcurrentHashMap()
for (int i = 0; i < 30; i++) {
String key = String.valueOf(i);
new Thread(()->{
map.put(key,UUID.randomUUID().toString().substring(0,8));
System.out.println(map);
},String.valueOf(i)).start();
}
}
}
公平锁与非公平锁 ReentrantLock lock = new ReentrantLock(false);//false非公平,true公平 底层实现sync = fair ? new FairSync() : new NonfairSync();
非公平锁:
缺点:造成线程饿死
优点:效率高
公平锁:
缺点:效率低一些
优点:线程均衡(比较礼貌)
可重入锁 synchronize(隐式)与lock(显式)
/**
* 乐观锁与悲观锁
* 乐观锁:支持并发操作,给每条数据加一个version
* <p>
* 悲观锁:不支持并发操作,拿到资源直接上锁,不要别的线程操作
* <p>
* 表锁:只要操作表里的任意一条数据,直接把整张表上锁
* <p>
* 行锁:操作哪条数据给哪条数据上锁(可能会发生死锁)
* <p>
* 读锁:共享锁
* <p>
* 写锁:独占锁
* <p>
* 读锁与写锁都会发生死锁
*/
public class ReadWriteLockDemo {
/**
* ReentrantReadWrite
*
* @param args
*/
public static void main(String[] args) {
/**
* 没有使用读写锁时会出现
* 写入没有完成,已经被读出了
*/
MyCache myCache = new MyCache();
for (int i = 0; i < 5; i++) {
final int num = i;
new Thread(() -> {
myCache.put(num + "", num + "");
}, String.valueOf(i)).start();
}
for (int i = 0; i < 5; i++) {
final int num = i;
new Thread(() -> {
myCache.get(num + "");
}, String.valueOf(i)).start();
}
}
}
//资源
//关键字volatile
class MyCache {
private volatile Map<String, Object> map = new HashMap<>();
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); //读写锁
public void put(String string, Object obj) {
lock.writeLock().lock(); //写锁 独占锁
try {
System.out.println(Thread.currentThread().getName() + "写入" + string);
TimeUnit.MICROSECONDS.sleep(3000);
map.put(string, obj);
System.out.println(Thread.currentThread().getName() + "写完了" + string);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.writeLock().unlock();
}
}
public Object get(String str) {
Object result = null;
lock.readLock().lock(); //读锁 共享锁
try {
System.out.println(Thread.currentThread().getName() + "正在读取" + str);
TimeUnit.MICROSECONDS.sleep(3000);
result = map.get(str);
System.out.println(Thread.currentThread().getName() + "取出完成" + str);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.readLock().unlock();
}
return result;
}
}
* 将写入锁降级为读锁(读锁不能升级为写锁)
* 获取写锁,获取读锁,释放写锁,释放读锁
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
writeLock.lock();
readLock.lock();
writeLock.unlock();
readLock.unlock();
/**
* 线程池
* 实际开发,这三种方式都不会用,通过自定义线程池来避免资源耗尽
*
*/
public class ThreadPoolDemo {
public static void main(String[] args) {
//一池N线程
ExecutorService threadPool = Executors.newFixedThreadPool(5);
try {
for (int i = 0; i < 10; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"hello,pool");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
threadPool.shutdown();
}
//一池一线程
ExecutorService executorService = Executors.newSingleThreadExecutor();
//根据需求创建线程,可扩容,遇强则强
ExecutorService pool = Executors.newCachedThreadPool();
}
}
public class ThreadPoolDemo2 {
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(
2, 5, 2L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()
);
}
}