一、
线程
前台线程
后台线程:守卫线程 t.setDaemon(true)
状态
新生:Thread t=new Thread();t.setPriority(1~10);//设置优先级
就绪:t.start();lock.notify();
运行:交给CPU统一调度
死亡:修改循环条件,让其自然死亡
异常:InterruptedException :t.stop();
二、锁(读读是共享的(并行的),写写是排他的,读写/写读是排他的)
锁数据
并发访问的应用场景下,数据一致性
关系型数据库(脏读,幻读,不可重复读)
可重入锁:避免死锁现象(synchronized)
//同步代码块
public xxx add(){
//同一时间只能进一条线程
synchronized(T t){
...
t.notify();//通知另一条线程进入
t.notifyAll();//通知其他所有线程
}
}
public xxx remove(){
//同一时间只能进一条线程
synchronized(T t){
//无参:永久等待,直到被通知
//有参:最大等待时间,在参数时间内等待,若在此之前被通知,则提前结束等待;达到最大等待时间
会正常结束等待
t.wait([long timestamp]);//线程阻塞
Thread.sleep();//线程阻塞:休眠时间到,自动醒
...
}
}
//同步普通方法:锁对象为当前对象 this
public synchronized xxx method(...){
}
//同步静态方法:锁对象为当前类型对象 xxx.class
public static synchronized xxx method(...){
}
//java.util.concurrent
//Lock
//ReentrantLock
//ReentrantReadWriteLock
//fair
//true:公平锁(先到先得)
//false:抢占锁
//writelock/readlock
//同步代码块(基础)
public class LockTest {
private static Object lock= new Object();
//两个同步代码块,锁在同一把锁下面(先进入的运行后通知后进入的,后进入的等待前面的通知才能运行)
public static void first(){
System.out.println("first");
int count=0;
while(count<20){
synchronized (lock){
System.out.println("first "+(++count));
lock.notify();//通知
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void second(){
System.out.println("second");
int count=0;
while(count<20){
synchronized (lock){
try {
lock.wait(1000);//等待(接收通知)
System.out.println("second "+(++count));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//主线程:java 虚拟机启动
public static void main(String[] args) throws InterruptedException {
//子线程1
Thread first = new Thread(() -> first());
//子线程2
Thread second = new Thread(() -> second());
//设置second线程为后台守卫线程:和主线程同生共死(非守卫线程则不会)
// second.setDaemon(true);
//启动线程
first.start();
// first.setPriority(1);
second.start();
//主线程阻塞,等待first和second线程执行完毕
first.join();
second.join();
//最后输出
System.out.println("END");
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @Author
* @Date 2022/2/23
* @Description:读读是共享的(并行的),写写是排他的,读写/写读是排他的
*/
//读写锁(高级)
public class RWLockTest {
private List<Integer> arr=new ArrayList<>();
private ReentrantReadWriteLock rwlock= new ReentrantReadWriteLock(true);//公平锁
public void add(int...values){
try{
rwlock.writeLock().lock();//上锁(写锁:排他的)
for (int value : values) {
System.out.println(Thread.currentThread().getName()+" WRITE "+value);
arr.add(value);
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
rwlock.writeLock().unlock();//解锁
}
}
public void read(){
try{
rwlock.readLock().lock();
arr.forEach(e-> System.out.println(Thread.currentThread().getName()+" READ "+e));
try {
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
}finally {
rwlock.readLock().unlock();
}
}
public static void main(String[] args) {
RWLockTest rwLockTest = new RWLockTest();
ExecutorService pool =Executors.newCachedThreadPool();
Random rand = new Random();
for (int i = 0; i < 20; i++) {
final int _i =i;//进入线程里的必须是常量
pool.execute(()->{
if(rand.nextInt(2)==0){//随机判断多或写
int[] arr =new int[1+rand.nextInt(10)];
for (int j = _i*10,k=0; k <arr.length ; j++) {
arr[k++]=j;
}
rwLockTest.add(arr);
}else {
rwLockTest.read();
}
});
}
}
}