线程中级篇(一):基本并发容器
传统的容器并没有实现线程安全,所以在多线程的情况下,并不管用。本文首先自己手写一个并发Queue引出全文:
import java.util.LinkedList; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class MyQueue { //1 需要一个承装元素的集合 private LinkedList<Object> list = new LinkedList<Object>(); //2 需要一个计数器 private AtomicInteger count = new AtomicInteger(0); //3 需要制定上限和下限 private final int minSize = 0; private final int maxSize ; //4 构造方法 public MyQueue(int size){ this.maxSize = size; } //5 初始化一个对象 用于加锁 private final Object lock = new Object(); //put(anObject): 把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断,直到BlockingQueue里面有空间再继续. public void put(Object obj){ synchronized (lock) { while(count.get() == this.maxSize){ try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //1 加入元素 list.add(obj); //2 计数器累加 count.incrementAndGet(); //3 通知另外一个线程(唤醒) lock.notify(); System.out.println("新加入的元素为:" + obj); } } //take: 取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的数据被加入. public Object take(){ Object ret = null; synchronized (lock) { while(count.get() == this.minSize){ try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //1 做移除元素操作 ret = list.removeFirst(); //2 计数器递减 count.decrementAndGet(); //3 唤醒另外一个线程 lock.notify(); } return ret; } public int getSize(){ return this.count.get(); } public static void main(String[] args) { final MyQueue mq = new MyQueue(5); mq.put("a"); mq.put("b"); mq.put("c"); mq.put("d"); mq.put("e"); System.out.println("当前容器的长度:" + mq.getSize()); Thread t1 = new Thread(new Runnable() { @Override public void run() { mq.put("f"); mq.put("g"); } },"t1"); t1.start(); Thread t2 = new Thread(new Runnable() { @Override public void run() { Object o1 = mq.take(); System.out.println("移除的元素为:" + o1); Object o2 = mq.take(); System.out.println("移除的元素为:" + o2); } },"t2"); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } }
并发类容器是java.util.concurrent包中提供的用于并发编程的容器,主要有以下大类:
package com.xushu.multi; import java.util.Vector; public class Ticket { public static void main(String[] args) { final Vector<String> tickets = new Vector<String>(); for(int i = 1; i < 1000; i++){ tickets.add("火车票" + i); } 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(); } } }
DelayQueue的演示
WangMing.java
package com.xushu.multi; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; public class WangMing implements Delayed{ private String name; //身份证 private String id; //截止时间 private long endTime; //定义时间工具类 private TimeUnit timeUnit = TimeUnit.SECONDS; public WangMing(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 int compareTo(Delayed o) { WangMing w = (WangMing)o; return this.getDelay(this.timeUnit) - w.getDelay(this.timeUnit) > 0 ? 1 : 0; } /** * 用来判断是否到了截止时间 */ @Override public long getDelay(TimeUnit unit) { return endTime - System.currentTimeMillis(); } }
WangBa.java
package com.xushu.multi; import java.util.concurrent.DelayQueue; public class WangBa implements Runnable{ private DelayQueue<WangMing> queue = new DelayQueue<WangMing>(); public boolean yinye = true; public void shangji(String name,String id,int money){ WangMing man = new WangMing(name, id, 1000 * money + System.currentTimeMillis()); System.out.println("网名"+man.getName()+" 身份证"+man.getId()+"交钱"+money+"块,开始上机..."); this.queue.add(man); } public void xiaji(WangMing man){ System.out.println("网名"+man.getName()+" 身份证"+man.getId()+"时间到下机..."); } @Override public void run() { while(yinye){ WangMing man; try { man = queue.take(); xiaji(man); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { try{ System.out.println("网吧开始营业"); WangBa speed = new WangBa(); Thread shangwang = new Thread(speed); shangwang.start(); speed.shangji("路人甲", "123", 1); speed.shangji("路人乙", "234", 10); speed.shangji("路人丙", "345", 5); } catch(Exception e){ e.printStackTrace(); } } }
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java之关于JSTL引入问题
错误信息:Can not find the tag library descriptor for “http://java.sun.com/jstl/core”JSTL taglib需要jstl.jar来支持。在1.0和1.1版本的时候,还需要standard.jar来配合。但从1.2版本开始,jar文件名字变成了jstl-1.2.jar,也不再需要standard.jar了。另外,servlet 版本需要2.4以上。所以正确的做法是把jstl-1.2.jar放到WEB-INF/lib里面就可以了。或者通过maven来配置, <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> jstl版本低于1.2记得在maven依赖配置这个 不过一般情况都会使用高版本的jst <groupId>taglibs</groupId>...
- 下一篇
使用VSCode如何调试C#控制台程序_2_加深总结
原文: 使用VSCode如何调试C#控制台程序_2_加深总结 要想使用调试,必须创建项目 1-你要调式的类,控制台类等等,你需要放在一个项目下,这个项目最好是由使用.net core创建的,VSCode对应的命令为: dotnet new console(这里以控制台为例) 2-使用编译命令(dotnet restore)生成obj文件(包含project.xx.json等关于项目的重要文件) 或者使用运行命令:dotnet run (会自动编译) 3-在调试按钮下添加两个配置文件:launch.json和tasks.json: (tasks.json不需要做任何改动; launch.json需要修改属性值program: 原"program": "${workspaceRoot}/bin/Debug/<target-framework>/<project-name.dll>", 改为: "program": "${workspaceRoot}/bin/Debug/NETCoreApp1.1/新建文件夹.dll" 备注: 以控制台为例: 其中<targe...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- MySQL8.0.19开启GTID主从同步CentOS8
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Hadoop3单机部署,实现最简伪集群