java并发包下有很多内置的处理线程安全问题工具类,在集合中就有2种线程同步的类,比如:Vector较ArrayList线程安全,但是效率较低,同样的还有Hashtable和HashMap,在实际项目中常用ArrayList与HashMap,因为前者比重,影响执行效率
- 以下是java的几种并发包下的使用场景
1.CountDownLatch
CountDownLatch 同步器
1.1 原理:
- 运行多个或一个线程,等待其他多个或一个线程执行完毕,在执行当前线程
- java并发包下同步辅助类:定义计数器可以设定个数,每次调用countDown() 计数器中的个数就会减1,当计数器的个数等于0的时候,调用await方法时,就会执行await方法后面的代码,如果计数器个数大于0时,调用await时,是不会执行await后面的代码
1.2 使用场景:
- 有一个文件,需要2个线程执行读写操作,执行完写的操作才可以读取内容
实现:使用计数器CountDownLatch,计数器的个数为2,在每个写的线程执行完毕,调用countDown方法,在写的线程后面,调用计数器的await方法,await方法后面执行读线程,这样在读取数据时,可以保证数据的完整性
public class ThreadWrite implements Runnable {
private Poeple peo;
private Integer count;
private CountDownLatch cdl;
public ThreadWrite(Poeple peo, Integer count,CountDownLatch cdl) {
this.peo = peo;
this.count = count;
this.cdl = cdl;
}
@Override
public void run() {
System.out.println("ThreadWrite");
if (count == 0) {
peo.setName("小明");
peo.setSex("男");
} else if (count == 1) {
peo.setName("小红");
peo.setSex("女");
}
cdl.countDown();//每次执行同步器减一
}
}
public static void main(String[] args) {
Poeple peo = new Poeple();
CountDownLatch cdl = new CountDownLatch(2);//创建同步器,线程个数为2
new Thread(new ThreadWrite(peo, 1, cdl)).start();
new Thread(new ThreadWrite(peo, 1, cdl)).start();
try {
cdl.await();//等待同步器个数为0,执行后续代码
new Thread(new ThreadRead(peo)).start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
2. CyclicBarrier
CyclicBarrier 循环屏障
2.1 原理:
- 运行多个线程之间相互等待,执行完毕后在执行线程中await后面的代码
2.2 使用场景:
- 多个线程在执行计算操作,另一个线程需要将计算结果相加,创建一个屏障线程,等待其他线程执行后在执行屏障线程
- 多个线程中有需要全部执行完,最后执行的代码
/**
* 写线程
*/
public class ThreadWrite implements Runnable {
private Poeple peo;
private Integer count;
private CyclicBarrier cb;
public ThreadWrite(Poeple peo, Integer count, CyclicBarrier cb) {
this.peo = peo;
this.count = count;
this.cb = cb;
}
@Override
public void run() {
System.out.println("ThreadWrite");
/*循环屏障*/
try {
cb.await();//等待线程数等于,CyclicBarrier中parties个数,执行之前所有等待线程await后面的代码
System.out.println("循环屏障");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
/**
* 读取线程
*/
public class ThreadRead implements Runnable {
private Poeple peo;
public ThreadRead(Poeple peo) {
this.peo = peo;
}
@Override
public void run() {
synchronized (peo) {
System.out.println("ThreadRead");
System.out.println(peo.getName());
System.out.println(peo.getSex());
}
}
}
public static void main(String[] args) {
CyclicBarrier cb = new CyclicBarrier(4);//循环屏障
System.out.println("当前线程数"+cb.getParties());
System.out.println("当前线程等待数"+cb.getNumberWaiting());
Poeple peo = new Poeple();
int count = 0;
new Thread(new ThreadWrite(peo, count,cb)).start();
new Thread(new ThreadWrite(peo, count,cb)).start();
new Thread(new ThreadWrite(peo, count,cb)).start();
new Thread(new ThreadWrite(peo, count,cb)).start();
}
3. Semaphore
Semaphore:信号量
3.1 原理:
- java并发包下,可以处理一个及以上的线程的并发量
3.2 使用场景:
- 一个楼层,有2个入口,一个入口每次只能进1个人,每次可以进2个人,而使用synchronized,只有一个入口,每次只能进1个人,使用信号量可以提高处理并发的个数
public class ThreadWrite implements Runnable {
private Poeple peo;
private Integer count;
private Semaphore s;
private List<Poeple> peoList;
public ThreadWrite(List<Poeple> peoList, Integer count, Semaphore s) {
this.peoList = peoList;
this.count = count;
this.s = s;
}
@Override
public void run() {
/*信号量*/
try {
s.acquire();//获取锁
System.out.println("ThreadWrite");
Poeple poeple = new Poeple();
poeple.setName("name1");
poeple.setSex("nv");
peoList.add(poeple);
System.out.println(Thread.currentThread().getName() + "=========>" + peoList.size());
s.release();//释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Semaphore s = new Semaphore(3);//信号量 同时处理三个线程
List<Poeple> peo = new ArrayList<>();
int count = 0;
for (int i = 0; i < 20; i++) {
new Thread(new ThreadWrite(peo,count,s),"线程1").start();
new Thread(new ThreadWrite(peo,count,s),"线程2").start();
new Thread(new ThreadWrite(peo,count,s),"线程3").start();
}
}
- 实体类代码
public class Poeple {
private Integer id;
private String name;
private String sex;
public Poeple() {
}
public Poeple(Integer id, String name, String sex) {
this.id = id;
this.name = name;
this.sex = sex;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}