JUC编程

与JUC编程相关的包

一.线程和进程

一个进程往往包含多个线程,至少包含一个线程

java默认有几个线程?

mian线程和GC线程(垃圾回收)

对于java而言:Thread、Runnable、Callable

一般是他们来开启进程

java真的能开启线程么

java是不能开启线程的

public synchronized void start() {/*** This method is not invoked for the main method thread or "system"* group threads created/set up by the VM. Any new functionality added* to this method in the future may have to also be added to the VM.** A zero status value corresponds to state "NEW".*/if (threadStatus != 0)throw new IllegalThreadStateException();/* Notify the group that this thread is about to be started* so that it can be added to the group's list of threads* and the group's unstarted count can be decremented. */group.add(this);boolean started = false;try {start0();started = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {/* do nothing. If start0 threw a Throwable thenit will be passed up the call stack */}}
}
//调用start0   native是本地方法,需要去调用C++操作硬件的,java实现不了
private native void start0();

并行、并发

并发编程:并行、并发

并发(多线程操作同一个资源)

​ ·CPU一核,模拟出来多条线程,快速交替

并行(多个人一起行走)

​ ·CPU多核,多个线程可以同时进行

public class Test1 {public static void main(String[] args) {//获取CPU的核数//CPU密集型,IO密集型System.out.println(Runtime.getRuntime().availableProcessors());}
}

并发编程的本质:充分利用CPU的资源

线程的几个状态
public enum State {//新建NEW,//运行RUNNABLE,//阻塞BLOCKED,//等待WAITING,//超时等待TIMED_WAITING,//终止TERMINATED;
}
wait/sleep区别

1.来自不同的类

wait=》Object

sleep=》Thread

2.关于锁的释放

wait回释放锁的,而sleep是不会释放的

3.使用的范围不同

wait:必须在同步代码块中

sleep:可以在任何地方使用

4.是否需要捕获异常

wait不需要捕获异常

sleep必须要捕获异常(因为他可能会有超时等待)

二.Lock锁

传统的Synchronized
public class SaleTicketDemo01 {public static void main(String[] args) {//并发,多线程操作同一个资源类Ticket ticket = new Ticket();new Thread(()->{for (int i=0;i<60;i++) {ticket.sale();}},"A").start();new Thread(()->{for (int i=0;i<60;i++) {ticket.sale();}},"B").start();new Thread(()->{for (int i=0;i<60;i++) {ticket.sale();}},"C").start();}
}
//资源类  OOP
class Ticket{//属性,方法private int number = 50;//买票的方式public synchronized void sale(){if (number>0){System.out.println(Thread.currentThread().getName()+"卖出了"+(number--)+"票,还剩"+number+"张");}}
}

如果我们的买票方法没有synchronized修饰,则会出乱,没有顺序(synchronized也是非公平锁)

Lock接口


公平锁:可以先来后到:必须排队

非公平锁:不公平,可以插队(默认使用非公平锁

public class SaleTicketDemo02 {public static void main(String[] args) {//并发,多线程操作同一个资源类Ticket2 ticket = new Ticket2();new Thread(()->{ for (int i=0;i<60;i++) ticket.sale(); },"A").start();new Thread(()->{for (int i=0;i<60;i++) {ticket.sale();}},"B").start();new Thread(()->{for (int i=0;i<60;i++) {ticket.sale();}},"C").start();}
}
//lock3部曲
//1.new ReentrantLock()
//2.lock.lock()加锁
//3.finally { //解锁 lock.unlock(); }
//资源类  OOP
class Ticket2{//属性,方法private int number = 50;Lock lock = new ReentrantLock();//买票的方式public void sale(){//加锁lock.lock();try {if (number>0){System.out.println(Thread.currentThread().getName()+"卖出了"+(number--)+"票,还剩"+number+"张");}}catch (Exception e){e.printStackTrace();}finally {//解锁lock.unlock();}}
}

相当于手动挡的synchronized

Synchronized和Lock区别

1.Synchroized是一个内置的Java关键字,Lock是一个类

2.Synchroized无法判断读取锁的状态,Lock可以判断是否获取到锁

3.Synchroized会自动释放锁,lock必须手动释放锁,如果不释放锁,就会死锁

4.Synchroized 线程1(获得锁:阻塞)、线程2(等待锁,傻等),而lock锁不会傻等(lock.trylock()尝试获取锁)

5.Synchroized 可重入锁,不可中断的,非公平锁;

lock锁,也是可重入锁,可以判断锁状态,可以自己设置是非公平锁还是公平锁

6.Synchroized 适合锁少量的代码同步问题,Lock锁适合锁大量的同步代码

什么是锁,如何判断锁的是谁?

三.生产者和消费者问题

synchronized版本

package com.hkd.pc;/*** @author 王庆华* @version 1.0* @date 2020/11/13 11:50* @Description 线程之间的通信问题:生产者和消费者问题     等待唤醒,通知唤醒* @pojectname 线程交替执行  A    B   操作同一个变量  num = 0*                  A  num+1       B num-1*/
public class A {public static void main(String[] args) {Date date = new Date();new Thread(()->{for (int i=0;i<10;i++){try {date.increment();} catch (InterruptedException e) {e.printStackTrace();}}},"A").start();new Thread(()->{for (int i=0;i<10;i++){try {date.decrement();} catch (InterruptedException e) {e.printStackTrace();}}},"B").start();}
}
//判断等待,通知,业务
class Date{public int number = 0;//+1public synchronized void increment() throws InterruptedException {if (number!=0) {//等待this.wait();}number++;//通知其他线程,我+1完毕了System.out.println(Thread.currentThread().getName()+"=>"+number);this.notifyAll();}public synchronized void decrement() throws InterruptedException {if (number==0){//等待this.wait();}number--;//通知其他线程我-1完毕了System.out.println(Thread.currentThread().getName()+"=>"+number);this.notifyAll();}
}

问题:如果存在A B C D四个线程呢,线程还安全么

虚假唤醒问题

if改为while判断

即可解决虚假唤醒问题

JUC版本


  • class BoundedBuffer {final Lock lock = new ReentrantLock();final Condition notFull  = lock.newCondition(); final Condition notEmpty = lock.newCondition(); final Object[] items = new Object[100];int putptr, takeptr, count;public void put(Object x) throws InterruptedException {lock.lock(); try {while (count == items.length)notFull.await();items[putptr] = x;if (++putptr == items.length) putptr = 0;++count;notEmpty.signal();} finally { lock.unlock(); }}public Object take() throws InterruptedException {lock.lock(); try {while (count == 0)notEmpty.await();Object x = items[takeptr];if (++takeptr == items.length) takeptr = 0;--count;notFull.signal();return x;} finally { lock.unlock(); }}}
    

代码实现:

package com.hkd.pc;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @author 王庆华* @version 1.0* @date 2020/11/13 12:14* @Description TODO* @pojectname 线程相关*/
public class B {public static void main(String[] args) {Date date = new Date();new Thread(()->{for (int i=0;i<10;i++){try {date.increment();} catch (InterruptedException e) {e.printStackTrace();}}},"A").start();new Thread(()->{for (int i=0;i<10;i++){try {date.decrement();} catch (InterruptedException e) {e.printStackTrace();}}},"B").start();new Thread(()->{for (int i=0;i<10;i++){try {date.increment();} catch (InterruptedException e) {e.printStackTrace();}}},"C").start();new Thread(()->{for (int i=0;i<10;i++){try {date.decrement();} catch (InterruptedException e) {e.printStackTrace();}}},"D").start();}
}//判断等待,通知,业务
class Date1{public int number = 0;//+1Lock lock = new ReentrantLock();Condition condition = lock.newCondition();public void increment() throws InterruptedException {lock.lock();try {while (number!=0) {//等待condition.await();//等待}number++;//通知其他线程,我+1完毕了System.out.println(Thread.currentThread().getName()+"=>"+number);condition.signalAll();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public void decrement() throws InterruptedException {lock.lock();try {while (number==0) {//等待condition.await();//等待}number--;//通知其他线程,我-1完毕了System.out.println(Thread.currentThread().getName()+"=>"+number);condition.signalAll();} catch (Exception e) {e.printStackTrace();}finally {lock.unlock();}}
}

任何一个新技术,绝不是仅仅只是覆盖了原来的技术,而是优势和补充

问题:


不是ABCD的顺序

Condition精准的通知和唤醒技术

有序性

代码测试

package com.hkd.pc;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @author 王庆华* @version 1.0* @date 2020/11/13 19:12* @Description TODO* @pojectname 线程相关*/
public class C {public static void main(String[] args) {Data3 data = new Data3();//A执行完  调用B,B执行完调用C ,C执行完调用Anew Thread(()->{for (int i =0;i<10;i++){data.printA();}},"A").start();new Thread(()->{for (int i =0;i<10;i++){data.printB();}},"B").start();new Thread(()->{for (int i =0;i<10;i++){data.printC();}},"C").start();}
}
//资源类 lock锁
class Data3{private Lock lock = new ReentrantLock();private Condition condition1 = lock.newCondition();private Condition condition2 = lock.newCondition();private Condition condition3 = lock.newCondition();private int number=1;//1  A   2B    3Cpublic void printA(){lock.lock();try {//业务  判断  执行while (number!=1){condition1.await();}System.out.println(Thread.currentThread().getName()+"=>AAA");//唤醒,唤醒指定的人number=2;condition2.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public void printB(){lock.lock();try {//业务  判断  执行while (number!=2){condition2.await();}System.out.println(Thread.currentThread().getName()+"=>AAA");//唤醒,唤醒指定的人number=3;condition3.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public void printC(){lock.lock();try {//业务  判断  执行while (number!=3){condition3.await();}System.out.println(Thread.currentThread().getName()+"=>AAA");//唤醒,唤醒指定的人number=1;condition1.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}
}

保证了我们的有序性

四.八锁现象

对象、Class

情况一

synchronized关键字

锁的对象是方法的调用者

package com.hkd.lock8;import java.util.concurrent.TimeUnit;/*** @author 王庆华* @version 1.0* @date 2020/11/13 19:28* @Description TODO* //1.标准情况下:先打印是发短信还是打电话?--------》发短信* 2.我们发短信业务中暂停3S,现在先打印是发短信还是打电话?-----》发短信* 因为sendSms和call用的是synchronized关键字  锁的对象是方法的调用者* 两个方法是一个对象,用的同一把锁,谁先拿到谁先执行* @pojectname 线程相关*/
public class Test1 {public static void main(String[] args) throws InterruptedException {Phone phone = new Phone();new Thread(()->{phone.sendSms();},"A").start();TimeUnit.SECONDS.sleep(1);new Thread(()->{phone.call();},"B").start();}
}class Phone{public synchronized void sendSms(){try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("发短信snedSms");}public synchronized void call(){System.out.println("call");}
}

增加一个普通方法呢?

   Phone2 phone = new Phone2();new Thread(()->{phone.sendSms();},"A").start();TimeUnit.SECONDS.sleep(1);new Thread(()->{phone.hello();},"B").start();
public void hello(){System.out.println("hello  hello");
}

我们发现1S过后hello方法先执行

因为普通方法不受锁的影响

情况二

两个对象,两个同步方法

 Phone2 phone1 = new Phone2();Phone2 phone2 = new Phone2();new Thread(()->{phone1.sendSms();},"A").start();TimeUnit.SECONDS.sleep(1);new Thread(()->{phone2.call();},"B").start();
class Phone2{public synchronized void sendSms(){try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("发短信snedSms");}public synchronized void call(){System.out.println("call");}
}

call先打印,这个时候就跟延迟有关了,因为锁的对象不一样,谁快先调用谁

情况三

方法变成静态同步方法(static修饰)

public class Test3 {public static void main(String[] args) throws InterruptedException {Phone3 phone = new Phone3();new Thread(()->{phone.sendSms();},"A").start();TimeUnit.SECONDS.sleep(1);new Thread(()->{phone.call();},"B").start();}
}class Phone3{public static synchronized void sendSms(){try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("发短信snedSms");}public static synchronized void call(){System.out.println("call");}
}

我们发现发短信先打印

原因:

**1.**synchronized关键字锁的对象是方法的调用者,同一个对象,谁先拿到谁执行

**2.**static : 静态方法 类一加载就有了 是一个Class 模板

Phone3只有唯一的一个class对象 -–-–> Class phone3Class = Phone3.class;,因此,我们这个地方锁的的class,全局唯一,用的肯定是同一个锁

如:

Phone3 phone1 = new Phone3();
Phone3 phone2 = new Phone3();
new Thread(()->{phone1.sendSms();},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{phone2.call();},"B").start();

还是发短信先打印,也就印证了我们的Static修饰的同步方法,锁的就是Class,一定是谁先拿到谁先执行

情况四

一个对象+静态同步方法+普通同步方法

public class Test4 {public static void main(String[] args) throws InterruptedException {Phone4 phone = new Phone4();new Thread(()->{phone.sendSms();},"A").start();TimeUnit.SECONDS.sleep(1);new Thread(()->{phone.call();},"B").start();}
}class Phone4{//静态同步方法public static synchronized void sendSms(){try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("发短信snedSms");}//普通同步方法public  synchronized void call(){System.out.println("call");}
}

打电话先输出

原因:

锁的对象不同,前者锁的是Class类模板,后者锁的调用者

由于前者有延迟,锁对象不一样,后者不需要等解锁

两个对象+静态同步方法+普通同步方法

Phone4 phone = new Phone4();
Phone4 phone1 = new Phone4();
new Thread(()->{phone.sendSms();},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{phone1.call();},"B").start();

谁没有延迟(谁的低),谁先执行,

锁的对象不同,前者锁的是Class类模板,后者锁的调用者

由于前者有延迟,锁对象不一样,后者不需要等解锁

总结:

一个是new出来的对象 ,是一个具体的实例,可以多个同一类型的实例,那么锁就有可能不一样了

一个是Class类模板,锁的是这个类型的对象模板,Class模板全局唯一,锁的对象一定一样

五.集合类不安全

List不安全

代码

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();for (int i = 0; i<10;i++){new Thread(()->{list.add(UUID.randomUUID().toString().substring(0,5));System.out.println(list);},String.valueOf(i)).start();}}
}

错误:

Exception in thread “0” Exception in thread “4” Exception in thread “2” java.util.ConcurrentModificationException

并发修改异常

我们发现并发下List是不安全的

解决方案
1.使用Vector<>()
List<String> list = new Vector<>();

为什么安全呢?

我们的Vector源码中,官方在添加元素的时候给我们写了synchronized修饰add方法(比ArrayList早出来)

public synchronized void addElement(E obj) {modCount++;ensureCapacityHelper(elementCount + 1);elementData[elementCount++] = obj;
}
2.List顶层老大Collections工具类
List<String> list = Collections.synchronizedList(new ArrayList<>());

把我们的List变成线程安全

3.CopyOnWriteArrayList
List<String> list = new CopyOnWriteArrayList<>();
//CopyOnWriteArrayList源码
public CopyOnWriteArrayList() {setArray(new Object[0]);
}
private transient volatile Object[] array;

CopyOnWrite 写入时赋值

COW计算机程序设计领域的一种优化策略

多个线程调用的时候,list,读取的时候是固定的,写入的时候(覆盖操作)在写入的时候避免覆盖,造成数据问题

优点:

我们的Vector的add方法是synchronized来修饰了,效率比较低

我们再来看看CopyOnWriteArrayList的add方法

public boolean add(E e) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;Object[] newElements = Arrays.copyOf(elements, len + 1);newElements[len] = e;setArray(newElements);return true;} finally {lock.unlock();}
}

我们可以看出,CopyOnWriteArrayList是用lock锁,效率高

Set不安全

代码:

public class SetTest {public static void main(String[] args) {HashSet<String> set = new HashSet<>();for (int i=0;i<30;i++){new Thread(()->{set.add(UUID.randomUUID().toString().substring(0,5));System.out.println(set);},String.valueOf(i)).start();}}
}

同理错误类型为:java.util.ConcurrentModificationException

解决方案
1.Collections工具类
Set<String> set = Collections.synchronizedSet(new HashSet<>());
2.CopyOnWriteSet
Set<String> set = new CopyOnWriteArraySet<>();
HashSet底层源码

HashSet就是一个HashMap

public HashSet() {map = new HashMap<>();
}
//HashSet的add方法
//set本质就是map的key,key是唯一的,所以set是无序的
public boolean add(E e) {return map.put(e, PRESENT)==null;
}
private static final Object PRESENT = new Object();//常量

HashMap不安全

//map是这样用的么,
//默认等价于什么
Map<String,String> map = new HashMap<>();
Map<String,String> map = new HashMap<>(16,0.75);

Map源码

 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16  位运算16static final int MAXIMUM_CAPACITY = 1 << 30;static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认加载因子//初始容量
public HashMap(int initialCapacity) {this(initialCapacity, DEFAULT_LOAD_FACTOR);
}/*** Constructs an empty <tt>HashMap</tt> with the default initial capacity* (16) and the default load factor (0.75).*/
//加载因子
public HashMap() {this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}

代码

public class MapTest {public static void main(String[] args) {Map<String,String> map = new HashMap<>();for(int i=0;i<=60;i++){new Thread(()->{map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0,5));System.out.println(map);},String.valueOf(i)).start();}}
}

也会有并发修改错误

解决方案
1.Collections工具类
Map<String,String> map = Collections.synchronizedMap(new HashMap<>());
2.ConcurrentHashMap
Map<String,String> map = new ConcurrentHashMap<>();
//ConcurrentHashMap源码
public ConcurrentHashMap() {}
public ConcurrentHashMap(int initialCapacity) {if (initialCapacity < 0)throw new IllegalArgumentException();int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?MAXIMUM_CAPACITY :tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));this.sizeCtl = cap;}

六.Callable

1.可以有返回值

2.可以抛出异常

3.方法不同,run()/start

@FunctionalInterface
public interface Callable<V> {/*** Computes a result, or throws an exception if unable to do so.** @return computed result* @throws Exception if unable to compute a result*/V call() throws Exception;
}

函数式接口

我们发现函数泛型就是我们返回值的类型,泛型写那种类型,我们就返回那种类型

那么我们如何启动Callable呢?

我们看源码发现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2dwA682L-1605609859700)(C:\Users\王庆华\AppData\Roaming\Typora\typora-user-images\image-20201114184939059.png)]

Thread的构造函数重载都是Runable类型

那么Callable怎么跟Thread搭上关系

package com.hkd.callable;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;/*** @author 王庆华* @version 1.0* @date 2020/11/14 18:45* @Description TODO* @pojectname 线程相关*/
public class CallableTest {public static void main(String[] args) throws ExecutionException, InterruptedException {//怎么启动callable//new Thread(new Runnable()).start();// new Thread(new FutureTask<>(Callable)).start();;new Thread().start();MyThread myThread = new MyThread();FutureTask futureTask = new FutureTask(myThread);new Thread(futureTask,"A").start();new Thread(futureTask,"B").start();//结果会被缓存,效率高Object o = futureTask.get();System.out.println(o);}
}class MyThread implements Callable<String>{@Overridepublic String call() throws Exception {return "1234";}
}

细节:

1.有缓存的

2.结果可能需要等待,会阻塞

七.JUC常用的辅助类

1.CountDownLatch

public class CountDownLatchDemo {public static void main(String[] args) throws InterruptedException {//总数是6,必须要执行任务的时候,再使用CountDownLatch countDownLatch = new CountDownLatch(6);for (int i=1;i<=6;i++){new Thread(()->{System.out.println(Thread.currentThread().getName()+"走了");//倒计时完毕  减一countDownLatch.countDown();},String.valueOf(i)).start();}//等待计数器归零然后在向下执行countDownLatch.await();System.out.println("关门");}
}

原理:

countDownLatch.countDown(); :数量减一

countDownLatch.await();:等待计数器归零,然后在向下执行

每次有线程调用,他就会减一,当计数器为0的时候,await就会被唤醒,然后执行

2.CyclicBarrier

加法计数器

一个只是计数,一个是计数完,调用线程

public class CyclicBarrierTest {//集齐七颗龙珠,召唤龙珠//召唤龙珠的线程public static void main(String[] args) {CyclicBarrier cyclicBarrier =new CyclicBarrier(7,()->{System.out.println("召唤神龙");});for(int i=1 ;i<=7;i++ ){final int temp = i;new Thread(()->{System.out.println(Thread.currentThread().getName()+"收集第"+temp+"颗龙珠");try {cyclicBarrier.await();//等待} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}).start();}}
}

我们会在循环的时候不停的调用线程收集龙珠,直到7颗龙珠,也就是7个线程调用完,才会执行下面的操作

如果我们

new CyclicBarrier(8,()->{
System.out.println(“召唤神龙”);
});

然而我们的for还是7,那么他就会一直等待,收集满8个才会向下执行,这个时候就卡死到这了

3.Semaphore

Semaphore:信号量

6个汽车,三个车位 123进 456等 3走了可能4要进来

这个int可以理解为线程数量(停车位)

public class SemaphoreDemo {//限流public static void main(String[] args) {Semaphore semaphore = new Semaphore(3);for(int i=1;i<=6;i++){new Thread(()->{try {semaphore.acquire();System.out.println(Thread.currentThread().getName()+"抢到了车位");TimeUnit.SECONDS.sleep(2);System.out.println(Thread.currentThread().getName()+"离开了车位");} catch (InterruptedException e) {e.printStackTrace();}finally {semaphore.release();}},String.valueOf(i)).start();}}
}

原理:

**acquire()

JUC编程入门(高并发)相关推荐

  1. 《Java并发编程入门与高并发面试》or 《Java并发编程与高并发解决方案》笔记

    <Java并发编程入门与高并发面试>or <Java并发编程与高并发解决方案>笔记 参考文章: (1)<Java并发编程入门与高并发面试>or <Java并发 ...

  2. 尚硅谷-互联网大厂高频重点面试题 (第2季)JUC多线程及高并发

    本期内容包括 JUC多线程并发.JVM和GC等目前大厂笔试中会考.面试中会问.工作中会用的高频难点知识. 斩offer.拿高薪.跳槽神器,对标阿里P6的<尚硅谷_互联网大厂高频重点面试题(第2季 ...

  3. Java 高并发_JAVA并发编程与高并发解决方案 JAVA高并发项目实战课程 没有项目经验的朋友不要错过!...

    JAVA并发编程与高并发解决方案 JAVA高并发项目实战课程 没有项目经验的朋友不要错过! 1.JPG (37.82 KB, 下载次数: 0) 2018-12-3 09:40 上传 2.JPG (28 ...

  4. JavaWeb 并发编程 与 高并发解决方案

    在这里写写我学习到和自己所理解的 Java高并发编程和高并发解决方案.现在在各大互联网公司中,随着日益增长的互联网服务需求,高并发处理已经是一个非常常见的问题,在这篇文章里面我们重点讨论两个方面的问题 ...

  5. 01 - Java并发编程与高并发解决方案笔记-基础篇

    01 - Java并发编程与高并发解决方案笔记-基础篇 基础篇很重要!很重要!很重要!!!一定要理解和认真思考. 01 - Java并发编程与高并发解决方案笔记-基础篇 1.课程准备 2.并发编程基础 ...

  6. libevent c++高并发网络编程_高并发编程学习(2)——线程通信详解

    前序文章 高并发编程学习(1)--并发基础 - https://www.wmyskxz.com/2019/11/26/gao-bing-fa-bian-cheng-xue-xi-1-bing-fa-j ...

  7. 高并发编程_高并发编程系列:7大并发容器详解(附面试题和企业编程指南)...

    不知道从什么时候起,在Java编程中,经常听到Java集合类,同步容器.并发容器,高并发编程成为当下程序员需要去了解掌握的技术之一,那么他们有哪些具体分类,以及各自之间的区别和优劣呢? 只有把这些梳理 ...

  8. 高并发编程_高并发编程系列:全面剖析Java并发编程之AQS的核心实现

    在并发编程领域,AQS号称是并发同步组件的基石,很多并发同步组件都是基于AQS实现,所以想掌握好高并发编程,你需要掌握好AQS. 本篇主要通过对AQS的实现原理.数据模型.资源共享方式.获取锁的过程, ...

  9. java并发编程与高并发解决方案

    知识点 线程安全,线程封闭,线程调度,同步容器,并发容器,AQS,J.U.C,等等 高并发解决思路与手段 扩容:水平扩容.垂直扩容 缓存:Redis.Memcache.GuavaCache等 队列:K ...

  10. Linux IO多路复用之epoll网络编程,高并发的使用例子 (含源码)

    本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下: 客户端从标准输入读入一行,发送到服务端 服务端从网络读取一行,然 ...

最新文章

  1. 淘金尖端领域:全球量子技术最新投资趋势
  2. 6.Mybatis中的动态Sql和Sql片段(Mybatis的一个核心)
  3. 小熊电器、九阳、苏泊尔们的“颜价比”被外卖小哥“打回原形”
  4. 爬虫基础, 乱码问题, jupyter, urllib, requests, lxml, multiprocessing并发, session, beautifulsoup...
  5. oracle的connect by语句
  6. Nhibernate 对view 查询的几种方法
  7. Linux系统间文件双向同步搭建Unison版
  8. 怎么取消计算机的用户名和密码怎么设置密码,开机密码如何取消 电脑开机密码取消设置方法介绍...
  9. 今日恐慌与贪婪指数为54 等级由贪婪转为中立
  10. sp根据备份文件来创建DB
  11. H3C交换机配置DHCP服务器
  12. Android: app不被系统kill掉
  13. Atitit enhance dev effect提升开发效率的十大原理与方法v2 u66.docx Atitit enhance dev effect提升开发效率的十大原理 目录 1. 管理 2
  14. 2060显卡驱动最新版本_堪比显卡界中的小米,价格屠夫,1999的铭瑄RTX2060终结者体验...
  15. kx linux驱动下载,创新5.1声卡驱动kX Project Audio DriverV5.1免费版下载 - 下载吧
  16. gc buffer busy acquire 、gc buffer busy release
  17. 减持奈飞增持京东健康,“贝莱德们”为何开始偏爱中国企业?
  18. 小试ESP8266(一) 一只电阻, 几条语句, 摆脱深度睡眠反复重启的困扰
  19. 搭建自动化测试平台(selenium+testng+maven+svn+Jenkins)【转自galen2016】
  20. 如何用计算机产生随机数,如何在计算器产生随机数

热门文章

  1. java doubke类型转换为String_Java的基本数据类型你知道吗?
  2. 免安装mysql5.7.22_windows环境下安装MySQL5.7.22免安装版
  3. TypeScript:函数进阶
  4. MyBatis学习笔记(3)-动态SQL
  5. tensorflow学习笔记(3)梯度下降法进行曲线拟合和线性回归
  6. 低照度图像修复方法总结
  7. 深度学习笔记(四)——ResNet模型学习与复现
  8. 最大矩形面积(C++实现)
  9. SVM支持向量机算法详解
  10. 实验三:从整理上理解进程创建、可执行文件的加载和进程执行进程切换,重点理解分析fork、execve和进程切换...