栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JUC学习记录

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JUC学习记录

JUC学习记录
  • 前言
  • 一、Lambda表达式
  • 二、多线程不一定块
  • 三、线程
    • 1、线程同步
      • A.传统的synchronized方法
      • B.ReentrantLock
    • 2、线程通信
      • A.统一唤醒(存在虚假唤醒)
      • B.新版Lock之定向唤醒
  • 四、安全的Collection
  • 五、FutureTask关联Callable
  • 总结
  • 参考文献

前言

JUC学习记录,主要有lambda表达式之函数式编程,线程的同步与通信,如何关联Thread与Callable。

一、Lambda表达式
package com.xhu.java.juc;


@FunctionalInterface
interface Add {
    
    int add(int x, int y);

    
    default void testDefault(){}

    
    static void testStatic(){}
}


public class LambdaTes {
    
    public static void test1() {
        Add addQuote = (x, y) -> {
            return x + y;
        };
        System.out.println(addQuote.add(2, 4));
    }

    public static void main(String[] args) {
        test1();
    }
}

二、多线程不一定块
package com.xhu.java.juc;


public class ConcurrencyTest {
    //主、辅线程中需循环的次数
    public final static long COUNT = 1000000000;

    
    private static void concurrency() throws InterruptedException {
        long start = System.currentTimeMillis();
        //开辟一个线程
        Thread thread = new Thread(() -> {
            int a = 0;
            for (int i = 0; i < COUNT; i++) {
                a += 5;
            }
        });
        //执行开辟的线程
        thread.start();
        //主线程执行内容
        int b = 0;
        for (int i = 0; i < COUNT; i++) {
            b--;
        }
        //开辟的 线程合并到主线程
        thread.join();
        //全程结束,计算花费的总时间
        long expense = System.currentTimeMillis() - start;
        //显示花费的总时间
        System.out.println("concurrency expense is at " + expense + "ms");
    }

    
    private static void serial() {
        long start = System.currentTimeMillis();
        int a = 0;
        for (int i = 0; i < COUNT; i++) {
            a += 5;
        }
        int b = 0;
        for (int i = 0; i < COUNT; i++) {
            b--;
        }
        long expense = System.currentTimeMillis() - start;
        System.out.println("serial expense is at " + expense + "ms");
    }

    public static void main(String[] args) throws InterruptedException {
        concurrency();
        serial();

    }
}

三、线程 1、线程同步 A.传统的synchronized方法
package com.xhu.java.juc;


import java.util.concurrent.TimeUnit;


public class SynchronizedTest {
    public static void main(String[] args) {
        manipulateResource();
        System.out.println(new ClassLoader() {
        }.getName());
    }

    private static void manipulateResource() {
        //1.申请资源类
        Phone phone = new Phone();
        //2.多线程操作资源类
        new Thread(()->{phone.sendEmail();},"A").start();
        try {
            TimeUnit.MILLISECONDS.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(()->{phone.sendSMS();},"B").start();
        new Thread(()->{phone.test();},"C").start();
    }
}


class Phone {
    int a = 2;
    
    public synchronized void sendEmail() {
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("sendEmail");
    }

    
    public synchronized void sendSMS() {
        System.out.println("sendSMS");
    }
    public synchronized static void testStatic(){
        System.out.println("我锁this.getClass,与this无关");
    }
    public void test(){
        System.out.println(this.a);
        System.out.println("它们只是在争夺一个唯一的关于this的锁,并没有锁住this,我仍然可以操作this");
    }
}
B.ReentrantLock
package com.xhu.java.juc;

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


public class SaleTicketsTest {
    public static void main(String[] args) {//程入的一个入口
        //1.创建资源类
        TicketResource tr = new TicketResource();
        //2.生成多个线程操作同一资源类
        new Thread(() -> {
            for (int i = 0; i < 30; i++) tr.sale();
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 30; i++) tr.sale();
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 30; i++) tr.sale();
        }, "C").start();
    }

}


class TicketResource {
    //初始设定30张票
    private int ticketNum = 30;
    //申请可重入锁
    Lock lock = new ReentrantLock();

    
    public void sale() {
        //在修改资源类时才加锁,减少锁的细粒度,提高并发量。
        try {
            lock.lock();
            if (ticketNum < 1) return;
            System.out.println(Thread.currentThread().getName() + "卖出了第" + ticketNum-- + "张票" + "还剩" + ticketNum + "张票");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

2、线程通信 A.统一唤醒(存在虚假唤醒)
package com.xhu.java.juc;

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


public class ThreadCommunicationTest {
    public static void main(String[] args) {
        test1();
    }

    private static void test1() {
        Resource resource = new Resource();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    resource.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    resource.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    resource.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "C").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    resource.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "D").start();
    }
}

class Resource {
    //1.变量定义
    private int number = 0;
    //可重入非公平递归锁
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    //2.变量加1
    public void increment() throws InterruptedException {
        lock.lock();
        try {
            //1.判断
            while (number > 1) {
                condition.await();
            }
            //2.干活
            number++;
            System.out.println(Thread.currentThread().getName() + " " + number);
            //3.通知
            condition.signalAll();
        } finally {
            lock.unlock();
        }

    }

    //3.变量减1
    public void decrement() throws InterruptedException {
        lock.lock();
        try {
            //1.判断
            while (number < 1) {
                condition.await();
            }
            //2.干活
            number--;
            System.out.println(Thread.currentThread().getName() + " " + number);
            //3.通知
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    

}

B.新版Lock之定向唤醒
package com.xhu.java.juc;

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


public class DelicateSignal {
    public static void main(String[] args) {
        test1();
    }

    private static void test1() {
        ShareData sd = new ShareData();
        new Thread(() -> {
            for (int i = 0; i < 3; i++) sd.aMethod();
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 3; i++) sd.bMethod();
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 3; i++) sd.cMethod();
        }, "C").start();


    }
}


class ShareData {
    //定点通知,0表示A,1表示B,2表示C
    private int mark = 0;
    //生成锁,lock是一把锁,一个人拿去用了,另一个想用这一个唯一的锁就必须等待,(大家争夺该锁时需同步)
    private Lock lock = new ReentrantLock();
    //生成多个condition,将阻塞线程分类,挂到多个不同的列表上
    Condition c1 = lock.newCondition();
    Condition c2 = lock.newCondition();
    Condition c3 = lock.newCondition();

    //A工作内容
    public void aMethod() {
        System.out.println("A想用锁之前");
        lock.lock();
        System.out.println("A想用锁之后");
        try {
            while (mark != 0) {
                System.out.println("A开始等待");
                c1.await();
            }
            mark = ++mark % 3;
            System.out.println("A完成自己的工作内容,B来处理后续工作");
            c2.signal();
            System.out.println("通知阻塞的B线程");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    //B工作内容
    public void bMethod() {
        System.out.println("B想用锁之前");
        lock.lock();
        System.out.println("B想用锁之后");
        try {
            while (mark != 1) {
                System.out.println("B开始等待");
                c2.await();
            }
            mark = ++mark % 3;
            System.out.println("B完成自己的工作内容,C来处理后续工作");
            c3.signal();
            System.out.println("通知阻塞的C线程");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    //C工作内容
    public void cMethod() {
        System.out.println("C想用锁之前");
        lock.lock();
        System.out.println("C想用锁之后");
        try {

            while (mark != 2) {
                System.out.println("C开始等待");
                c3.await();
            }
            mark = ++mark % 3;
            System.out.println("C完成自己的工作内容,A来处理新的一轮工作");
            c1.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
            System.out.println("通知阻塞的A线程");
        }
    }
}

四、安全的Collection
package com.xhu.java.juc;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;


public class ArrayListTest {
    //线程不安全,没有加任何同步机制
    public static List list = new ArrayList<>();
    //线程安全,写了一个继承SynchronizedCollection的静态内部类,里面有ArrayList一样的功能,该子类不仅实现了List,还加了同步代码块,锁了this
    public static List safeList = Collections.synchronizedList(new ArrayList<>());
    //读写分离,读的时候不加锁,提高并发,写的时候加锁,写的时候是写在了新数组里面,然后改变数组引用。(分两份,读用原本的,写时复制一份)
    public static List safeList2 = new CopyOnWriteArrayList<>();
    //类似于上面的CopyOnWriteArrayList
    public static Set safeSet = new CopyOnWriteArraySet<>();
    //为synchronized去锁new Node节点。
    public static Map safeMap = new ConcurrentHashMap<>();
    public static void testArrayList() {
        concurrentForList();
        try {
            Thread.sleep(2000);
            System.out.println(list.size());
            Thread.sleep(1000);
            System.out.println(list.size());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    private static void concurrentForList() {
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                for (int j = 0; j < 100000; j++) {
                    synchronized (list) {
                        list.add(UUID.randomUUID().toString().substring(0, 9));
                    System.out.println(list);
                    }
                }
            }, String.valueOf(i)).start();
        }
    }

    public static void main(String[] args) {
        testArrayList();
    }
}
五、FutureTask关联Callable
package com.xhu.java.juc;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;


public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        test1();
    }

    private static void test1() throws InterruptedException, ExecutionException {

        FutureTask f = new FutureTask<>(new MyCallable());
        new Thread(f, "A").start();
        Integer i = f.get();
        System.out.println(i);
    }
}

class MyCallable implements Callable {
    @Override
    public Integer call() throws Exception {
        return 1024;
    }
}
总结

1)Java8后支持的函数式编程,专注核心逻辑,实现一定义,多种快速重写。
2)线程的同步与通信,线程的调度必须的两点。
3)老版synchronized和新版Lock,新版功能强大。
4)新版安全的Collection,主要有读写分离思想的写时复制。
5)Callable关联Thread,靠的是中间子类FutureTask。

参考文献

[1] JUC 尚硅谷周阳

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/671356.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号