背景:并发知识是一个程序员段位升级的体现,同样也是进入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. python 防止sql注入字符串拼接的正确用法

    在使用pymysql模块时,在使用字符串拼接的注意事项错误用法1 sql='select * from where id="%d" and name="%s" ...

  2. 基于udp的套接字编程

    一,简单明了了解udp套接字编程 客户端: #Author : Kelvin #Date : 2019/1/30 11:07 from socket import * ip_conf=("1 ...

  3. Spring Boot 入门教程 | 图文讲解

    目录 一.Spring Boot 是什么 二.为什么要使用 Spring Boot 三.快速入门 3.1 创建 Spring Boot 项目 3.2 项目结构 3.3 引入 Web 依赖 3.4 编写 ...

  4. Vue.js-10:第十章 - 组件间的数据通信

    一.前言 在上一章的学习中,我们继续学习了 Vue 中组件的相关知识,了解了在 Vue 中如何使用组件的 data.prop 选项.在之前的学习中有提到过,组件是 Vue 中的一个非常重要的概念,我们 ...

  5. asp.net core系列 50 Identity 授权(中)

    1.5 基于策略的授权 在上篇中,已经讲到了授权访问(authorization)的四种方式.其中Razor Pages授权约定和简单授权二种方式更像是身份认证(authentication) ,因为 ...

  6. ES 15 - Elasticsearch中的数据类型 (text、keyword、date、geo等)

    目录 1 核心数据类型 1.1 字符串类型 - string(不再支持) 1.1.1 文本类型 - text 1.1.2 关键字类型 - keyword 1.2 数字类型 - 8种 1.3 日期类型 ...

  7. Vuex的初探与实战

    1.背景 最近在做一个单页面的管理后台项目,为了提高开发效率,使用了Vue框架来开发.为了使各个部分的功能,独立结构更加清晰,于是就拆分了很多组件,但是组件与组件之间数据共享成了一个问题,父子组件实现 ...

  8. RazorPage 小测试,作下记录

    @page@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf@{}@functions{ public AppInfo item { ...

  9. windows代码,传入文件名,遍历此目录下所有文件.

    #include <windows.h> #include <vector> using namespace std; BOOL IterAtorFileSaveFile(IN ...

  10. 【响应式编程的思维艺术】 (5)Angular中Rxjs的应用示例

    目录 一. 划重点 二. Angular应用中的Http请求 三. 使用Rxjs构建Http请求结果的处理管道 3.1 基本示例 3.2 常见的操作符 四. 冷热Observable的两种典型场景 4 ...