背景:并发知识是一个程序员段位升级的体现,同样也是进入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. OsharpNS轻量级.net core快速开发框架简明入门教程-Osharp.Redis使用

    OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...

  2. Flask导入静态文件问题

    然而如果使用flask开发web,并且需要在本地导入已经写好的css js 文件或者image一系列,这些文件是静态文件,需要另外建一个文件夹static;并且在html文件修改导入方法,exampl ...

  3. surging如何使用swagger 组件测试业务模块

    1.前言 微服务架构概念的提出已经有非常长一段时间了,但在近期几年却开始频繁地出现,大家都着手升级成微服务架构,使用着各种技术,大家认为框架有服务治理就是微服务,实现单一协议的服务调用,微服务虽然没有 ...

  4. 性能测试工具Locust的使用

    一.写在前面 官网:https://www.locust.io/ 官方使用文档:https://docs.locust.io/en/latest/ 大并发量测试时,建议在linux系统下进行. 二.L ...

  5. FreeSql 与 SqlSugar 性能测试(增EFCore测试结果)

    这篇文章受大家邀请,与 SqlSugar 做一次简单的性能测试对比.主要针对插入.批量插入.批量更新.读取性能的测试: 测试环境 .net core 2.2 FreeSql 0.3.17 sqlSug ...

  6. Scrapy爬虫遇到 ‘Forbidden by robots.txt’的问题

    今天在爬知乎精华时,出现了‘Forbidden by robots.txt’的问题 了解到到scrapy在爬取设定的url之前,它会先向服务器根目录请求一个txt文件,这个文件规定了爬取范围 scra ...

  7. 面试前必须知道的MySQL命令【explain】

    前言 只有光头才能变强 刷面试题的时候,不知道你们有没有见过MySQL这两个命令:explain和profile(反正我就见过了).. 之前虽然知道这两个命令大概什么意思,但一直没有去做笔记.今天发现 ...

  8. C:\Program Files\Java\jdk1.7.0_79\bin\java.exe'' finished with non-zero exit value 1

    转载请标明出处:https://www.cnblogs.com/tangZH/p/10538982.html 今天,在项目过程中碰到了这个奇怪的问题,C:\Program Files\Java\jdk ...

  9. Luogu P5284 [十二省联考2019]字符串问题

    好难写的字符串+数据结构问题,写+调了一下午的说 首先理解题意后我们对问题进行转化,对于每个字符串我们用一个点来代表它们,其中\(A\)类串的点权为它们的长度,\(B\)类串的权值为\(0\) 这样我 ...

  10. ASP.NET Core 使用 SignalR 遇到的 CORS 问题

    问题 将 SignalR 集成到 ASP.NET Core MVC 程序的时候,按照官方 DEMO 配置完成,但使用 DEMO 页面建立连接一直提示如下信息. Access to XMLHttpReq ...