同步类容器都是线程安全的,在某些场景下,需要枷锁保护符合操作,最经典ConcurrentModifiicationException,原因是当容器迭代的过程中,被并发的修改了内容。

for (Iterator iterator = tickets.iterator(); iterator.hasNext();) {
String string = (String) iterator.next();
tickets.remove(20);
}

  

//多线程使用Vector或者HashTable的示例(简单线程同步问题)
public class Tickets {
public static void main(String[] args) {
//初始化火车票池并添加火车票:避免线程同步可采用Vector替代ArrayList HashTable替代HashMap
final Vector<String> tickets = new Vector<String>(); Map<String, String> map = Collections.synchronizedMap(new HashMap<String, String>()); for(int i = 1; i<= 1000; i++){
tickets.add("火车票"+i);
} // for (Iterator iterator = tickets.iterator(); iterator.hasNext();) {
// String string = (String) iterator.next();
// tickets.remove(20);
// } for(int i = 1; i <=10; i ++){
new Thread("线程"+i){
public void run(){
while(true){
if(tickets.isEmpty()) break;
System.out.println(Thread.currentThread().getName() + "---" + tickets.remove(0));
}
}
}.start();
}
}
}

  同步类容器:如古老的Vector、HashTable。都是通过Collections.synchronized等工厂方法去创建实现的,底层用传统的synchronized关键字对每个共用的方法进行同步,使得每次只能有一个线程访问容器的状态。

并发类容器是专门针对并发设计的。ConCurrentHashMap替代HashTable。使用CopyOnWriteArrayList代替Voctor,CopyonWriteArraySet,并发的Queue,ConcurrentLinkedQueue高性能队列,LinkedBlockingQueue阻塞形式的队列

ConCurrentHashMap接口有两个实现

ConcurentHashMap

ConcurentSkipListMap(支持排序功能)

ConcurentHashMap内部使用段(Segment)来表示不同的部分,每个段就是一个小的HashTable,有自己的锁,只要多个修改操作,发生在不同的段上,就可以并发进行。

把一个整体分成16个段,最高支持16个线程的并发修改操作,在多线程中减小锁的粒度,从而降低锁竞争的一种方案,共享变量使用了volatile关键字声明,目的是第一时间获取修改的内容。

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; public class UseConcurrentMap {
public static void main(String[] args) {
ConcurrentHashMap<String,Object> chm=new ConcurrentHashMap<String, Object>();
chm.put("k1", "v1");
chm.put("k1", "v7777");//覆盖
chm.put("k2", "v2");
chm.put("k3", "v3");
chm.putIfAbsent("k4", "vvvv"); //存在 就不放入了
chm.putIfAbsent("k4", "555");
System.out.println(chm.get("k2"));
System.out.println(chm.size());
for (Map.Entry<String,Object> me:chm.entrySet()){
System.out.println("key:" + me.getKey() + ",value:" + me.getValue());
}
}
}

  

import java.util.concurrent.TimeUnit;

public class TimeUinitTest {
private TimeUnit timeUnit = TimeUnit.DAYS;
public static void main(String[] TimeUinitTest) {
TimeUinitTest tut = new TimeUinitTest();
tut.outInfo();
}
public void outInfo() {
System.out.println(timeUnit.name());
System.out.println(timeUnit.toDays(1));
System.out.println(timeUnit.toHours(1));
System.out.println(timeUnit.toMinutes(1));
System.out.println(timeUnit.toSeconds(1));
System.out.println(timeUnit.toMillis(1));
System.out.println(timeUnit.toMicros(1));
System.out.println(timeUnit.toNanos(1));
System.out.println((timeUnit.convert(1, TimeUnit.DAYS)) + timeUnit.name());
System.out.println((timeUnit.convert(24, TimeUnit.HOURS)) + timeUnit.name());
System.out.println((timeUnit.convert(1440, TimeUnit.MINUTES)) + timeUnit.name());
System.out.println("-------------------");
}
}

  

public class Task implements Comparable<Task>{
private int id ;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int compareTo(Task task){
return this.id>task.id?1:(this.id<task.id?-1:0);
}
public String toString(){
return this.id + "," + this.name;
}
}

  

Copy-On-Write容器:程序设计中的优化策略

两种:CopyOneWriteArrayList和CopyOnWriteArraySet

Copy-On-Write容器为写时复制的容器,当往一个容器添加元素的时候,不直接往当前容器添加,而是将当前容器就行Copy,复制出一个新的容器,然后新的容器中添加元素,添加完元素之后,在将原容器的引用指向新容器。

可以对CopyOneWrite容器进行并发的读,不需要枷锁,当前容器不会添加任何元素,所以CopyOnWrite也是一种读写分离的思想,读和写在不同的容器中

import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet; public class UseCopyOnWrite {
public static void main(String[] args) {
CopyOnWriteArrayList<String> cwal=new CopyOnWriteArrayList<String>();
CopyOnWriteArraySet<String> cwas = new CopyOnWriteArraySet<String>();
}
}

  并发Queue:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;

  

public class UseQueue {
public static void main(String[] args) throws Exception { //高性能无阻塞无界队列:ConcurrentLinkedQueue offer和add是没有区别的 ConcurrentLinkedQueue<String> q = new ConcurrentLinkedQueue<String>();
q.offer("a");
q.offer("b");
q.offer("c");
q.offer("d");
q.add("e"); System.out.println(q.poll()); //a 从头部取出元素,并从队列里删除
System.out.println(q.size()); //4
System.out.println(q.peek()); //b
System.out.println(q.size()); //4 ArrayBlockingQueue<String> array = new ArrayBlockingQueue<String>(5);
array.put("a");
array.put("b");
array.add("c");
array.add("d");
array.add("e");
array.add("f");
//System.out.println(array.offer("a", 3, TimeUnit.SECONDS)); //阻塞队列
LinkedBlockingQueue<String> q = new LinkedBlockingQueue<String>();
q.offer("a");
q.offer("b");
q.offer("c");
q.offer("d");
q.offer("e");
q.add("f");
//System.out.println(q.size()); // for (Iterator iterator = q.iterator(); iterator.hasNext();) {
// String string = (String) iterator.next();
// System.out.println(string);
// } List<String> list = new ArrayList<String>();
System.out.println(q.drainTo(list, 3));
System.out.println(list.size());
for (String string : list) {
System.out.println(string);
} final SynchronousQueue<String> q = new SynchronousQueue<String>();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(q.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() { @Override
public void run() {
q.add("asdasd");
}
});
t2.start();
}
}

  BlockingQueue接口:(下面的全是阻塞的)

import java.util.concurrent.PriorityBlockingQueue;

public class UsePriorityBlockingQueue {
public static void main(String[] args) throws Exception{ PriorityBlockingQueue<Task> q = new PriorityBlockingQueue<Task>(); Task t1 = new Task();
t1.setId(3);
t1.setName("id为3");
Task t2 = new Task();
t2.setId(4);
t2.setName("id为4");
Task t3 = new Task();
t3.setId(1);
t3.setName("id为1"); //return this.id > task.id ? 1 : 0;
q.add(t1); //3
q.add(t2); //4
q.add(t3); //1 // 1 3 4
System.out.println("容器:" + q);
System.out.println(q.take().getId());
System.out.println("容器:" + q);
System.out.println(q.take().getId());
System.out.println(q.take().getId());
}
}

  

 //没有缓存的队列,生产者产生的数据会被消费者直接消费掉
final SynchronousQueue<String> q = new SynchronousQueue<String>(); Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("进入到t1线程中,阻塞等待获取元素");
System.out.println("消费"+q.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
TimeUnit.SECONDS.sleep(2);
Thread t2 = new Thread(new Runnable() { @Override
public void run() {
q.add("asdasd");
}
});
t2.start();
}

  

import java.util.concurrent.DelayQueue;

public class WangBa implements Runnable{
private DelayQueue<Wangmin> queue=new DelayQueue<Wangmin>();
public boolean yinye =true; public void shangji(String name,String id,int money){
Wangmin man = new Wangmin(name, id, 1000 * money + System.currentTimeMillis());
System.out.println("网名"+man.getName()+" 身份证"+man.getId()+"交钱"+money+"块,开始上机...");
this.queue.add(man);
}
public void xiaji(Wangmin man){
System.out.println("网名"+man.getName()+" 身份证"+man.getId()+"时间到下机...");
} @Override
public void run() {
while(yinye){
try {
Wangmin man = queue.take();
xiaji(man);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static void main(String args[]){
try{
System.out.println("网吧开始营业");
WangBa siyu = new WangBa();
Thread shangwang = new Thread(siyu);
shangwang.start(); siyu.shangji("路人甲", "123", 1);
siyu.shangji("路人乙", "234", 10);
siyu.shangji("路人丙", "345", 5);
}
catch(Exception e){
e.printStackTrace();
}
}
}

  

import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit; public class Wangmin implements Delayed {
private String name;
//身份证
private String id;
//截止时间
private long endTime;
//定义时间工具类
private TimeUnit timeUnit = TimeUnit.SECONDS; public Wangmin(String name,String id,long endTime){
this.name=name;
this.id=id;
this.endTime = endTime;
} public String getName(){
return this.name;
} public String getId(){
return this.id;
} /**
* 用来判断是否到了截止时间
*/
@Override
public long getDelay(TimeUnit unit) {
//return unit.convert(endTime, TimeUnit.MILLISECONDS) - unit.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS);
return endTime - System.currentTimeMillis();
} /**
* 相互批较排序用
*/
@Override
public int compareTo(Delayed delayed) {
Wangmin w = (Wangmin)delayed;
return this.getDelay(this.timeUnit) - w.getDelay(this.timeUnit) > 0 ? 1:0;
}
}

  AQS锁:

Thread A = new Thread(new Runnable() {

			@Override
public void run() {
int sum = 0;
for(int i =0; i < 10; i ++){
sum += i;
}
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LockSupport.park(); //后执行
System.err.println("sum: " + sum);
}
}); A.start(); Thread.sleep(1000); LockSupport.unpark(A); //先执行

  

Java线程同步类容器和并发容器(四)的更多相关文章

  1. Java并发——同步容器与并发容器

    同步容器类 早期版本的JDK提供的同步容器类为Vector和Hashtable,JDK1.2 提供了Collections.synchronizedXxx等工程方法,将普通的容器继续包装.对每个共有方 ...

  2. Java并发—同步容器和并发容器

    简述同步容器与并发容器 在Java并发编程中,经常听到同步容器.并发容器之说,那什么是同步容器与并发容器呢?同步容器可以简单地理解为通过synchronized来实现同步的容器,比如Vector.Ha ...

  3. java多线程总结-同步容器与并发容器的对比与介绍

    1 容器集简单介绍 java.util包下面的容器集主要有两种,一种是Collection接口下面的List和Set,一种是Map, 大致结构如下: Collection List LinkedLis ...

  4. java 线程同步 原理 sleep和wait区别

    java线程同步的原理java会为每个Object对象分配一个monitor, 当某个对象(实例)的同步方法(synchronized methods)被多个线程调用时,该对象的monitor将负责处 ...

  5. Java线程同步之一--AQS

    Java线程同步之一--AQS 线程同步是指两个并发执行的线程在同一时间不同时执行某一部分的程序.同步问题在生活中也很常见,就比如在麦当劳点餐,假设只有一个服务员能够提供点餐服务.每个服务员在同一时刻 ...

  6. Java线程同步的四种方式详解(建议收藏)

    ​ Java线程同步属于Java多线程与并发编程的核心点,需要重点掌握,下面我就来详解Java线程同步的4种主要的实现方式@mikechen 目录 什么是线程同步 线程同步的几种方式 1.使用sync ...

  7. Java线程同步_1

    Java线程同步_1 synchronized 该同步机制的的核心是同步监视器,任何对象都可以作为同步监视器,代码执行结束,或者程序调用了同步监视器的wait方法会导致释放同步监视器 synchron ...

  8. java线程 同步临界区:thinking in java4 21.3.5

    java线程 同步临界区:thinking in java4 21.3.5 thinking in java 4免费下载:http://download.csdn.net/detail/liangru ...

  9. JAVA - 线程同步和线程调度的相关方法

    JAVA - 线程同步和线程调度的相关方法 wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁:wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等 ...

随机推荐

  1. 洛谷P4380 [USACO18OPEN]Multiplayer Moo

    题目 第一问: 用广搜类似用\(floodfill\)的方法. 第二问: 暴力枚举加剪枝,对于每个连通块,枚举跟这个连通块相连的其他与他颜色不同的连通块,然后向外扩展合并颜色与他们俩相同的连通块.扩展 ...

  2. 微信小程序搜索框代码组件

    search.wxml <view class="header"> <view class="search"> <icon typ ...

  3. Time of Trial

    Time of Trial(思维) 题目大意:一个人想逃,一个人要阻止那个人逃跑 ,阻止者念每一个符咒的时间为b[i],逃跑者念每一个符咒的时间为a[i],逃跑者如果念完了第i个符咒,阻止者还没有念完 ...

  4. 刷题之给定一个整数数组 nums 和一个目标值 taget,请你在该数组中找出和为目标值的那 两个 整数

    今天下午,看了一会github,想刷个题呢,就翻出来了刷点题提高自己的实际中的解决问题的能力,在面试的过程中,我们发现,其实很多时候,面试官 给我们的题,其实也是有一定的随机性的,所以我们要多刷更多的 ...

  5. 剑指offer:删除链表中重复的结点

    题目描述: 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理 ...

  6. pycharm 当有多个.py文件在开发环境中时,如何操作可以保证运行当前面对自己的文件?

    Alt+shift+F10选择自己的py文件,执行就可以了.

  7. mongodb配置“主从”模式

    版本的mongodb不支持Master/slave模式了.推荐使用集群模式.大家都知道,集群模式需要多于三台的奇数台机器(奇数个进程测试有意义,实际意义不大)现在我的手头有两台主机,更合理的配置个人觉 ...

  8. Linux下限制某程序CPU占用

    CentOS 7下CPULimit的部署与使用途中 部署 git clone https://github.com/opsengine/cpulimit.git cd cpulimit make cp ...

  9. oracle sequnece 介绍以及 监控

    ###sequnece 介绍 http://www.dba-oracle.com/t_rac_tuning_sequence_order_parameter.htm order by 可能会影响性能, ...

  10. [LeetCode] 787. Cheapest Flights Within K Stops K次转机内的最便宜航班

    There are n cities connected by m flights. Each fight starts from city u and arrives at v with a pri ...