线程安全的类:
Vector与ArrayList:
实现的原理都是通过数组实现的,查询速度比较快,增加,删除修改的速度比较慢。数组的增加和删除需要涉及到数据的copy。所以速度会慢一些。
区别:
Vector是线程安全的,方法使用synchronized关键字,使用同步函数来保证线程的安全。
ArrayList是线程不安全,但是效率是比较高的
LinkedList 是线程不安全的,增加和修改的速度比较快,查询的速度比较慢。
HashTable与HashMap的区别:
HashTable 是线程安全的,方法使用synchronized 关键字修饰,效率非常低,存在锁的竞争资源。
HashMap 是线程不安全的,是通过链表加数组的方式实现的。
ConcurrentHashMap–分段式锁。
分段原理:讲一个整体拆分成小的hashTable。默认分成16段。
ConcurrentHashMap: 内部使用段来表示这些不同的部分,每一段
其实就是一个小的HashTable,他们都有自己锁,只要多个修改操作发生在不同的段上,他们就可以并发执行进行。把一个整体分成16段,(也就是最高支持16个线程并发执行。)这也是在重线程场景中减少锁的粒度,从而降低锁竞争的一种方案,。并且在代码中大多数的共享变量,使用volatile关键字声明,目的是第一时间获取修改的内容,性能非常好。
package com.itmayiedu.day03;
import java.util.concurrent.CountDownLatch;
public class CoundDownLatchDemo01 {
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(2);//设置初始值为2
System.out.println("我是主线程。。。。。。");
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("================>>>>>>>>>我是子线程1,开始执行任务");
try{
Thread.sleep(1000);
countDownLatch.countDown();//每次减1
System.out.println("=================>>>>>>>>>>子线程1,正在执行任务。。。。");
}catch (Exception ex){
}
System.out.println("===================>>>>>>>>子线程1执行任务结束。。");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("=====================>>>>>>>>>我是子线程2,开始执行任务。。");
try {
Thread.sleep(1000);
countDownLatch.countDown();//每次减1
System.out.println("=============>>>>>>>>>>子线程2,正在执行。。。。");
}catch (Exception ex){
}
System.out.println("================>>>>>>>子线程2执行结束。。。");
}
}).start();
try{
countDownLatch.await();//如果countDown不为0 的话 就处于一直等待状态,等于0的话就执行下面的代码块
}catch (Exception ex){
}
System.out.println("主线程开始执行任务。。。");
for (int i = 0; i <10 ; i++) {
System.out.println("=========>>>>>>"+i+" "+Thread.currentThread().getName());
}
}
}
CyclicBarrier也可以当作计数器使用:当线程的数量达到指定的数量是线程并发执行。
package com.itmayiedu.day03;
import java.util.concurrent.CyclicBarrier;
class write extends Thread{
CyclicBarrier cyclicBarrier;
public write(CyclicBarrier cyclicBarrier){
this.cyclicBarrier =cyclicBarrier;
}
@Override
public void run() {
System.out.println("开始写入数据。。。。。。");
try{
Thread.sleep(4000);
}catch (Exception ex){
}
System.out.println(Thread.currentThread().getName()+" "+"数据写入成功");
try{
cyclicBarrier.await();//当前线程处于等到状态,所有的线程执行完毕在执行其后的代码。
}catch (Exception ex){
}
//等所有的线程执行完毕后在执行这段代码。
System.out.println(Thread.currentThread().getName()+" 所有数据执行完毕");
}
}
public class CyclicBarrierDemo01 {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
write write = new write(cyclicBarrier);
Thread t1 = new Thread(write);
Thread t2 = new Thread(write);
Thread t3 = new Thread(write);
Thread t4 = new Thread(write);
Thread t5 = new Thread(write);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
Semaphore:
是一种基于计数 的信号量,他可以是一个阀值,基于此多个线程竞争获取许可信号,做自己的申请后归还,超过阀值后,线程申请许可信号将会被阻塞,Semaphore可以用来构建一些对象池,资制这也叫二元信号量,标示两种互斥状态,
用法如下:
availablePermits函数用来获取当前可用的资源数量。
wc.acquire():申请资源。
wc.release();释放资源。