- 前言
- 一、Lambda表达式
- 二、多线程不一定块
- 三、线程
- 1、线程同步
- A.传统的synchronized方法
- B.ReentrantLock
- 2、线程通信
- A.统一唤醒(存在虚假唤醒)
- B.新版Lock之定向唤醒
- 四、安全的Collection
- 五、FutureTask关联Callable
- 总结
- 参考文献
一、Lambda表达式JUC学习记录,主要有lambda表达式之函数式编程,线程的同步与通信,如何关联Thread与Callable。
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 尚硅谷周阳



