背景:并发知识是一个程序员段位升级的体现,同样也是进入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 web 框架,才不会从入门到放弃 -- 简单登录页面

    上一节,我们基本了解了 Django 的一些配置,这一节,我们将通过一个简单的登录页面,进一步学习 Django 的使用. 新建项目 首先,新建一个 Django 项目,记得别弄错了哦. settin ...

  2. Filter中排除对指定URL的过滤

    1. 我们可以在web.xml中配置filter来对指定的URL进行过滤,进行一些特殊操作如权限验证等. <!– session过滤filter –> <filter> < ...

  3. socketserver实现并发

    socketserver实现并发原理:给每一个前来链接的客户端开启一个线程执行通信.也就是给每一个连接“配备”了一个管家. 下面用一个简单的示例来演示socketserver实现并发(一个服务端,两个 ...

  4. centos 修改hostname

    centos修改主机名的正确方法 1 centos6下修改hostname [root@centos6 ~]$ hostname # 查看当前的hostnmae centos6.magedu.com ...

  5. C#读写Excel的几种方法

    1 使用Office自带的库 前提是本机须安装office才能运行,且不同的office版本之间可能会有兼容问题,从Nuget下载 Microsoft.Office.Interop.Excel 读写代 ...

  6. 把时间留给重要的事——Markdown 模板功能上线

    你是否遇到过因为同事在任务中过于放飞自我而感到头疼?或者经历过因为内容描写的不系统而导致关键信息被忽视? 现在,CODING Markdown 模板功能将帮助你解决这些困扰. 功能介绍 CODING ...

  7. Prncnfg.vbs参数详解

    语法: Cscript Prncnfg {-g | -t | -x | -?} [-S <ServerName>] [-P <PrinterName>] [-z <New ...

  8. [FromBody]与[FromForm]区别

    [FromBody]与[FromForm]区别 1,fromBody:在cation方法传入参数后添加[frombody]属性,参数将以一个整体的josn对象的形式传递. 2,fromform:在ca ...

  9. Java Excel导入导出(实战)

    一.批量导入(将excel文件转成list) 1. 前台代码逻辑 1)首先在html页面加入下面的代码(可以忽略界面的样式) <label for="uploadFile" ...

  10. python列表的交、并、差集

    #!/usr/bin/env python3 l1 = ['] l2 = ['] # 交集 result1 = [i for i in l1 if i in l2] result2 = list(se ...