背景:并发知识是一个程序员段位升级的体现,同样也是进入BAT的必经之路,有必要把并发知识重新梳理一遍。

并发concurrent:

使用ThreadLocal可以实现线程范围内共享变量,线程A写入的值和线程B获取到的结果一致;ReentrantReadWriteLock允许多个读线程或多个写线程同时进行,但不允许写线程和读线程同时进行;使用Callable可以得到线程执行的返回结果;Exchanger可以相互交换家线程执行的结果;这些使用方法大致都一样,JDk参考文档里面哪里不会点哪里,下面写个ThreadLocal实现线程范围内变量共享,里面还用到了一下饿汉模式:

执行结果如图中控制台打印,使用ThreadLocal保证了线程0和线程1读取到的值与写入的一致。

 import java.util.Random;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import lombok.Data; public class ThreadLocalTest {
//ThreadLocal 实现线程范围内共享变量
private static ThreadLocal<Integer> x = new ThreadLocal<Integer>();
private static ThreadLocal<MyThreadScopeData> myThreadScopeData = new ThreadLocal<MyThreadScopeData>();
public static void main(String[] args) {
new ReentrantReadWriteLock();
for(int i = 0; i<2; i++) {
new Thread(new Runnable() {
@Override
public void run() {
int data = new Random().nextInt();
System.out.println(Thread.currentThread().getName()
+" has put data: "+ data);
x.set(data); // 存的时候与当前线程相关 取的时候也是与当前线程相关
//MyThreadScopeData.getInstance()拿到与本线程实例相关的对象: 不用反复new对象来getter/setter
MyThreadScopeData.getThreadInstance().setName("name: "+data);
MyThreadScopeData.getThreadInstance().setAge(data);
new A().get();
new B().get();
}
}).start();
}
} static class A{
public void get() {
int data = x.get();
System.out.println("A from "+Thread.currentThread().getName()+" get data: "+data);
//MyThreadScopeData.getInstance()拿到与本线程实例相关的对象
MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();
System.out.println("A from "+Thread.currentThread().getName()
+" getMyData: "+myData.getName() +","+myData.getAge());
}
} static class B{
public void get() {
int data = x.get();
System.out.println("B from "+Thread.currentThread().getName()+" get data: "+data);
//MyThreadScopeData.getInstance()拿到与本线程实例相关的对象
MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();
System.out.println("B from "+Thread.currentThread().getName()
+" getMyData: "+myData.getName() +","+myData.getAge());
}
} //设计自己线程范围内变量的共享,不需要创建对象,只需调用线程即可用到线程内的变量
@Data
static class MyThreadScopeData{
//构造方法私有化,外部没发直接调用,但是可以调用里面的静态方法
private MyThreadScopeData() { }
public static /*synchronized*/ MyThreadScopeData getThreadInstance() {
MyThreadScopeData instance = map.get();
if (instance == null) {
//饿汉模式 : 第一次来创建
instance = new MyThreadScopeData();
map.set(instance);
}
return instance;
}
// private static MyThreadScopeData instance = null; // new MyThreadScopeData();
private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>();
private String name;
private int age;
} }

网上还有一个多线程面试很有趣的题目:子线程执行10次,主线程执行100次,接着子线程再执行10次,主线程继续再执行100次,往复循环50次;

 //Java多线程面试: 子线程执行10次,主线程执行100次,接着子线程再10次,主线程再执行100次,往复循环50次
public class ThreadCommunication {
public static void main(String[] args) {
Business business = new Business();
new Thread(
new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 50; i++) {
business.sub(i);
}
}
}).start(); for (int i = 1; i <= 50; i++) {
business.main(i);
}
} //把主线程和自线程执行的方法归结到一个类(共同算法的若干方法),巧妙设计,好维护高聚合,健壮性;
public static class Business{
//子线程方法
private boolean bShouldSub = true;
public synchronized void sub(int i) {
while(!bShouldSub) {
//用while比if更好,可以防止线程被伪唤醒
try {
this.wait(); // 如果不是子线程方法该执行的,则令其等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j = 1; j<= 10; j++) {
System.out.println("sub thread sequence of "+j + ",loop of "+ i);
}
bShouldSub = false;
this.notify(); //唤醒主线程方法
} //主线程方法
public synchronized void main(int i) {
while(!bShouldSub) {
try {
this.wait(); // 如果不是主线程方法该执行的,则令其等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j = 1; j<= 100; j++) {
System.out.println("main thread sequence of "+j + ",loop of "+ i);
}
bShouldSub = true;
this.notify(); // 唤醒子线程方法
}
}
}

线程池:

1、固定线程数目的线程池newFixedThreadPool;

2、缓存线程数目的线程池newCachedThreadPool;

3、单一线程池newSingleThreadExecutor;

4、定时器线程池newScheduledThreadPool;

 package com.xinyan.springcloud.controller;

 import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; public class ThreadPoolTest {
public static void main(String[] args) {
//固定线程数目的线程池 3个
ExecutorService threadPool = Executors.newFixedThreadPool(3);
//缓存线程数目的线程池即动态变化 当任务过来了,线程池内部会自动增加线程,空闲后线程又被回收,线程数目不定
//ExecutorService threadPool = Executors.newCachedThreadPool();
//单一线程池
//ExecutorService threadPool = Executors.newSingleThreadExecutor();
//往线程池中放入10个任务:
for(int i = 1; i<= 10; i++) {
final int task = i; // task被final修饰不能变了,但是i 可以变
threadPool.execute(new Runnable() {
@Override
public void run() {
for(int j =1; j<=10; j++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//System.out.println(Thread.currentThread().getName()+" loop of "+ j +" task is "+ task);
}
}
});
}
System.out.println("所有的10个任务已经全部提交。"); //任务都提交了,交由线程池去搞
threadPool.shutdown(); //没有任务后关闭线程
//threadPool.shutdownNow(); //还有任务没有给执行完毕就立即关闭线程 //定时器线程池: 3个线程
System.out.println("敌军还有5秒到达战场.");
Executors.newScheduledThreadPool(3).schedule(new Runnable() {
@Override
public void run() {
System.out.println("敌军抵达战场,碾碎她们。");
}
//5秒后执行线程池内run方法
}, 5, TimeUnit.SECONDS);
//Executors.newScheduledThreadPool(3)scheduleAtFixedRate(command, initialDelay, period, unit)
//scheduleAtFixedRate 定时循环执行线程池内方法
}
}

并发concurrent---2的更多相关文章

  1. Java并发---concurrent包

    一.包的结构层次 其中包含了两个子包atomic和locks,另外字concurrent下的阻塞队列以及executor,这些就是concurrent包中的精华.而这些类的实现主要是依赖于volati ...

  2. 并行parallel和并发concurrent的区别

    http://stackoverflow.com/questions/1050222/concurrency-vs-parallelism-what-is-the-difference Concurr ...

  3. java 并发 concurrent Executor

    Excutor类 Executor 执行提交的对象Runnable任务. ExecutorService 一个Executor ,提供方法来管理终端和方法,可以产生Future为跟踪一个或多个异步任务 ...

  4. Java虚拟机6:内存溢出和内存泄露、并行和并发、Minor GC和Full GC、Client模式和Server模式的区别

    前言 之前的文章尤其是讲解GC的时候提到了很多的概念,比如内存溢出和内存泄露.并行与并发.Client模式和Server模式.Minor GC和Full GC,本文详细讲解下这些概念的区别. 内存溢出 ...

  5. iOS 处理多个网络请求的并发的情况

    如何处理多个网络请求的并发的情况 一.概念 1.并发 当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配 ...

  6. 并发concurrent---1

    背景:并发知识是一个程序员段位升级的体现,同样也是进入BAT的必经之路,有必要把并发知识重新梳理一遍. 并发concurrent: 说到并发concurrent,肯定首先想到了线程,创建线程有两种方法 ...

  7. python多进程并发和多线程并发和协程

    为什么需要并发编程? 如果程序中包含I/O操作,程序会有很高的延迟,CPU会处于等待状态,这样会浪费系统资源,浪费时间 1.Python的并发编程分为多进程并发和多线程并发 多进程并发:运行多个独立的 ...

  8. java并发编程概念

    并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其 ...

  9. 《C#并发编程经典实例》学习笔记-关于并发编程的几个误解

    误解一:并发就是多线程 实际上多线程只是并发编程的一种形式,在C#中还有很多更实用.更方便的并发编程技术,包括异步编程.并行编程.TPL 数据流.响应式编程等. 误解二:只有大型服务器程序才需要考虑并 ...

随机推荐

  1. 再谈ERP选型

    这几天收到老友的消息,谈及他们公司ERP选型的结果,基本上确定了使用Oracle EBS,因此闹了接近一年的选SAP还是选Oracle的纷争落下帷幕. 这家企业我去年曾去交流过,跟他们聊了一下ERP行 ...

  2. [日志分析] Access Log 日志分析

    0x00.前言: 如何知道自己所在的公司或单位是否被入侵了?是没人来“黑”,还是因自身感知能力不足,暂时还没发现?入侵检测是每个安全运维人员都要面临的严峻挑战.安全无小事,一旦入侵成功,后果不堪设想. ...

  3. 审计篇丨PHPcms9.6.3后台XSS审计

    引言 今天与大家分享的文章是关于审计思路的知识点,用到的是PHPcms的最新版本,因为常规扫描无法进入后台,所以我们修改了代码让扫描器爬虫爬到后台. 漏洞复现环境 安装PHPstudy 安装PHPcm ...

  4. <转载>Android性能优化之HashMap,ArrayMap和SparseArray

    本篇博客来自于转载,打开原文地址已经失效,在此就不贴出原文地址了,如原作者看到请私信我可用地址,保护原创,人人有责.   Android开发者都知道Lint在我们使用HashMap的时候会给出警告—— ...

  5. Cron表达式详解【转】

    Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式: Seconds Minutes Hours DayofMonth Month ...

  6. MobileForm控件的使用方式-用.NET(C#)开发APP的学习日志

    今天继续Smobiler开发APP的学习日志,这次是做一个title.toolbar.侧边栏三种效果 样式一 一.          Toolbar 1.       目标样式 我们要实现上图中的效果 ...

  7. 理解css之position属性

    之前css学的一直不精致而且没有细节,为了成为一个完美的前端工作人员,所以决定重新学习css的属性.当然会借鉴MDZ文档(MDZ文档)或其他博主的经验来总结.在这里会注明借鉴或引用文章的出处.侵权即删 ...

  8. Android studio无法创建类和接口问题解决办法。提示 Unable to parse template "Class"

    重新配置了studio 的工作环境, 没问题,后来加需求要新增java类和接口,这就出现问题了,新建的时候,就会报错: Unable to parse template "Interface ...

  9. FFmpeg开发实战(六):使用 FFmpeg 将YUV数据编码为视频文件

    本文中实现的一个小功能是把一个YUV原始视频数据(时间序列图像)经过h264编码为视频码流,然后在使用mp4封装格式封装. 编码&封装的流程图如下: 使用ffmpeg编码流程: 1.首先使用a ...

  10. 从一张图开始,谈一谈.NET Core和前后端技术的演进之路

    从一张图开始,谈一谈.NET Core和前后端技术的演进之路 邹溪源,李文强,来自长沙.NET技术社区 一张图 2019年3月10日,在长沙.NET 技术社区组织的技术沙龙<.NET Core和 ...