并发concurrent---2
背景:并发知识是一个程序员段位升级的体现,同样也是进入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的更多相关文章
- Java并发---concurrent包
一.包的结构层次 其中包含了两个子包atomic和locks,另外字concurrent下的阻塞队列以及executor,这些就是concurrent包中的精华.而这些类的实现主要是依赖于volati ...
- 并行parallel和并发concurrent的区别
http://stackoverflow.com/questions/1050222/concurrency-vs-parallelism-what-is-the-difference Concurr ...
- java 并发 concurrent Executor
Excutor类 Executor 执行提交的对象Runnable任务. ExecutorService 一个Executor ,提供方法来管理终端和方法,可以产生Future为跟踪一个或多个异步任务 ...
- Java虚拟机6:内存溢出和内存泄露、并行和并发、Minor GC和Full GC、Client模式和Server模式的区别
前言 之前的文章尤其是讲解GC的时候提到了很多的概念,比如内存溢出和内存泄露.并行与并发.Client模式和Server模式.Minor GC和Full GC,本文详细讲解下这些概念的区别. 内存溢出 ...
- iOS 处理多个网络请求的并发的情况
如何处理多个网络请求的并发的情况 一.概念 1.并发 当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配 ...
- 并发concurrent---1
背景:并发知识是一个程序员段位升级的体现,同样也是进入BAT的必经之路,有必要把并发知识重新梳理一遍. 并发concurrent: 说到并发concurrent,肯定首先想到了线程,创建线程有两种方法 ...
- python多进程并发和多线程并发和协程
为什么需要并发编程? 如果程序中包含I/O操作,程序会有很高的延迟,CPU会处于等待状态,这样会浪费系统资源,浪费时间 1.Python的并发编程分为多进程并发和多线程并发 多进程并发:运行多个独立的 ...
- java并发编程概念
并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其 ...
- 《C#并发编程经典实例》学习笔记-关于并发编程的几个误解
误解一:并发就是多线程 实际上多线程只是并发编程的一种形式,在C#中还有很多更实用.更方便的并发编程技术,包括异步编程.并行编程.TPL 数据流.响应式编程等. 误解二:只有大型服务器程序才需要考虑并 ...
随机推荐
- Arduino入门笔记(6):温度传感器及感温杯实验
转载请注明:@小五义 http://www.cnblogs.com/xiaowuyi 欢迎加入讨论群 64770604 一.本次实验所需器材 1.Arduino板 :https://item.taob ...
- 启动VMware虚拟机时总是出现许可证到期提示怎么办?
不知道大家有没有遇到过这个问题,每次当你打开VMware虚拟机时它总是会提示许可证到期,需要注册,还会出现许多报红的代码,下面就让小编带大家解决一下吧~ VMware教程 如果Fusion本身无法启动 ...
- ASP.NET Core中使用GraphQL - 最终章 Data Loader
ASP.NET Core中使用GraphQL - 目录 ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间 ...
- Git操作GitHub时的Proxy配置
无论是使用Android Studio中,VCS >> Git >> Clone, 还是直接Git Clone命令,clone GitHub项目时,出现错误提示:LibreSS ...
- 浅谈MySQL架构体系
一 数据库和数据库实例 在MySQL的学习研究中,存在两个非常容易混淆的概念,即数据库和数据库实例.在MySQL中,数据库和数据库实例定义如下: 数据库:存储数据的集合: 数据库实例:操作数据库的集 ...
- Changes of user relationship in AD can't be correctly synchronized to SCSM
The relationship of users might be not correctly updated if related users were once re-named in AD o ...
- Windows Server 2016-Netdom Join之客户端加域(二)
上章节我们介绍了如何通过图形化界面实现用户加域操作,本章节为大家简单介绍如何通过netdom join命令实现计算机加域操作.具体信息如下: 将工作站或成员服务器加入域.将计算机加入域的行为会为域中的 ...
- Error:"MetaStoreClient lost connection. Attempting to reconnect (1 of 24) after 5s. getCurrentNotificationEventId" occurs as HiveServer2 fails to start as it cannot connect to Metastore in HDP 3.0
SupportKB Problem Description:After upgrading to HDP 3.0, the HiveServer2 fails to start and the fol ...
- Win7 + CentOS7 双系统
记录一下更改系统启动菜单的方法. 前提: 1. 先安装 Win7 在硬盘第一分区,其它分区在 Win7 下处于未分配状态. 2. 再安装 CentOS 到上述未分配分区.(注意:手动分区时,可以留一定 ...
- VS2013 百度云资源以及密钥
https://pan.baidu.com/s/1eu3XycWO8fWItmkFeYNv9w提取码:dy9r 密钥:BWG7X-J98B3-W34RT-33B3R-JVYW9 vs2015 http ...