线程安全概念:当多个线程访问某一个类(对象或方法)时,这个对象始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的。

分析:当多个线程访问myThread的run方法时,以排队的方式进行处理(这里排对是按照CPU分配的先后顺序而定的),一个线程想要执行synchronized修饰的方法里的代码:1 尝试获得锁  2 如果拿到锁,执行synchronized代码体内容;拿不到锁,这个线程就会不断的尝试获得这把锁,直到拿到为止,而且是多个线程同时去竞争这把锁。(也就是会有锁竞争的问题)

synchronized:可以在任意对象及方法上加锁,而加锁的这段代码称为"互斥区"或"临界区"。取得的锁都是对象锁,而不是把一段代码(方法)当做锁,所以代码中哪个线程先执行synchronized关键字的方法,哪个线程就持有该方法所属对象的锁(Lock),在静态方法上加synchronized关键字,表示锁定.class类,类一级别的锁(独占.class类)。

锁对象的改变问题:例如下面代码中,当lock发生变化后,t1开始后,t2直接开始。如果去掉将lock改变的代码,则是t1结束后t2才会开始。但是同一对象属性的修改不会影响锁的情况,比如下面代码的lock现在是一个带属性的对象,如果改变该对象的属性,结果还是t1结束后t2才会开始。

package com.bjsxt.base.sync006;
/**
* 锁对象的改变问题
* @author alienware
*
*/
public class ChangeLock { private String lock = "lock"; private void method(){
synchronized (lock) {
try {
System.out.println("当前线程 : " + Thread.currentThread().getName() + "开始");
lock = "change lock";
Thread.sleep(2000);
System.out.println("当前线程 : " + Thread.currentThread().getName() + "结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) { final ChangeLock changeLock = new ChangeLock();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
changeLock.method();
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
changeLock.method();
}
},"t2");
t1.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
} }

 死锁问题:在设计程序时就应该避免双方相互持有对方的锁的情况,如下代码,会发生死锁问题,t1 进入lock1执行, t2 进入lock2执行。之后,t1去等待lock2对象解锁,t2去等待lock1对象解锁,这时谁也不能解锁,程序就会停在这里一直等待,这就是死锁问题。

package com.bjsxt.base.sync006;

/**
* 死锁问题,在设计程序时就应该避免双方相互持有对方的锁的情况
* @author alienware
*
*/
public class DeadLock implements Runnable{ private String tag;
private static Object lock1 = new Object();
private static Object lock2 = new Object(); public void setTag(String tag){
this.tag = tag;
} @Override
public void run() {
if(tag.equals("a")){
synchronized (lock1) {
try {
System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock1执行");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock2执行");
}
}
}
if(tag.equals("b")){
synchronized (lock2) {
try {
System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock2执行");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock1) {
System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock1执行");
}
}
}
} public static void main(String[] args) { DeadLock d1 = new DeadLock();
d1.setTag("a");
DeadLock d2 = new DeadLock();
d2.setTag("b"); Thread t1 = new Thread(d1, "t1");
Thread t2 = new Thread(d2, "t2"); t1.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
} }

volatile:用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的值。volatile很容易被误用,用来进行原子性操作。volatile关键字不具备synchronized关键字的原子性(同步)

AtomicInteger:一个提供原子操作的Integer的类。在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。注意:atomic类只保证本身方法的原子性,并不保证多次操作的原子性。比如说,我们使用AtomicInteger进行一次加十操作是具有原子性的,而同样是加十的操作,分成先加1,再加2,再加3,再加4这样四次操作,就不能保证原子性了。

脏读 :脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。

在线程里调用变量变量必须用final修饰

wait释放锁,notify不释放锁。配合synchronized会有不实时的问题,这时有了下面的类。

CountDownLatch:一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

主要方法

public CountDownLatch(int count); 初始化计时器数量

public void countDown();

public void await() throws InterruptedException

构造方法参数指定了计数的次数

countDown方法,当前线程调用此方法,则计数减一

await方法,调用此方法会一直阻塞当前线程,直到计时器的值为0

ThreadLocal:ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

多线程中的单例模式:

1.静态内部类--static inner class(饥汉模式)

package com.bjsxt.base.conn011;

public class Singletion {

    private static class InnerSingletion {
private static Singletion single = new Singletion();
} public static Singletion getInstance(){
return InnerSingletion.single;
} }

2.双重确认--dubble check instance(懒汉模式)

package com.bjsxt.base.conn011;

public class DubbleSingleton {

    private static DubbleSingleton ds;

    public  static DubbleSingleton getDs(){
if(ds == null){
try {
//模拟初始化对象的准备时间...
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (DubbleSingleton.class) {
if(ds == null){
ds = new DubbleSingleton();
}
}
}
return ds;
} public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(DubbleSingleton.getDs().hashCode());
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(DubbleSingleton.getDs().hashCode());
}
},"t2");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(DubbleSingleton.getDs().hashCode());
}
},"t3"); t1.start();
t2.start();
t3.start();
} }

同步类容器(不建议使用)

并发类容器

并发Queue:

Futuer模式

Master-Worker模式

JAVA高并发处理------多线程的更多相关文章

  1. Java高并发-多线程基础

    一.什么是线程 线程是进程内的执行单元. 二.线程的基本操作 2.1 状态与操作 2.2 新建线程 Thread t1 = new Thread(new CreateThread()); t1.sta ...

  2. java web开发 高并发处理

    转自:http://blog.csdn.net/zhangzeyuaaa/article/details/44542161 java处理高并发高负载类网站中数据库的设计方法(java教程,java处理 ...

  3. java中的多线程高并发与负载均衡的用途

    感觉对于这两问题的描述,大家很迷惑把 .下面我就介绍一下: 一; 什么是java的高并发,在什么情况下产生的? 答:如果网站的访问量非常大的话,我们就应该考虑高并发的情况. 高并发的时候就是有很多用户 ...

  4. java高并发系列 - 第16天:JUC中等待多线程完成的工具类CountDownLatch,必备技能

    这是java高并发系列第16篇文章. 本篇内容 介绍CountDownLatch及使用场景 提供几个示例介绍CountDownLatch的使用 手写一个并行处理任务的工具类 假如有这样一个需求,当我们 ...

  5. java并发编程笔记(十一)——高并发处理思路和手段

    java并发编程笔记(十一)--高并发处理思路和手段 扩容 垂直扩容(纵向扩展):提高系统部件能力 水平扩容(横向扩容):增加更多系统成员来实现 缓存 缓存特征 命中率:命中数/(命中数+没有命中数) ...

  6. Java高并发与多线程(二)-----线程的实现方式

    今天,我们开始Java高并发与多线程的第二篇,线程的实现方式. 通常来讲,线程有三种基础实现方式,一种是继承Thread类,一种是实现Runnable接口,还有一种是实现Callable接口,当然,如 ...

  7. Java高并发与多线程(三)-----线程的基本属性和主要方法

    今天,我们开始Java高并发与多线程的第三篇,线程的基本属性和主要方法. [属性] 编号(ID) 类型long 用于标识不同的线程,编号唯一,只存在java虚拟机的一次运行 名称(Name) 类型St ...

  8. Java高并发与多线程(四)-----锁

    今天,我们开始Java高并发与多线程的第四篇,锁. 之前的三篇,基本上都是在讲一些概念性和基础性的东西,东西有点零碎,但是像文科科目一样,记住就好了. 但是本篇是高并发里面真正的基石,需要大量的理解和 ...

  9. java高并发系列 - 第21天:java中的CAS操作,java并发的基石

    这是java高并发系列第21篇文章. 本文主要内容 从网站计数器实现中一步步引出CAS操作 介绍java中的CAS及CAS可能存在的问题 悲观锁和乐观锁的一些介绍及数据库乐观锁的一个常见示例 使用ja ...

随机推荐

  1. redis主从同步收到以下参数影响

      repl-ping-slave-period主从心跳ping的时间间隔.默认10 repl-timeout  从节点超时时间.默认60 repl-backlog-size  主节点保存操作日志的大 ...

  2. C#判断系统是64位还是32位 支持.net4.0以前的版本

    C#判断系统是64位还是32位的时候引用了一串代码,这个代码是从园子里面其他博文中转载过来的,引入自己的项目中发现无法使用,在引用了相应的命名空间之后还是提示: "未能找到类型或命名空间名称 ...

  3. Python基础——字典和有序字典

    字典 说明: 在 Python 中, 字典 是一系列 键 — 值对 .每个键都与一个值相关联,你可以使用键来访问与之相关联的值.与键相关联的值可以是数字.字符串.列表乃至字典.事实上,可将任何 Pyt ...

  4. Ajax知识总结

    一 AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). AJAX 不是新的编程语言,而是一种使用现有标准的新方法.AJAX 最大 ...

  5. 首层nginx 传递 二级代理,三级代理......多级代理nginx 客户端真实IP的方法

    首层nginx(172.25.10.1):先获取真实IP($remote_addr),再将真实IP传递给X-Forwarded-For    proxy_set_header X-Real-IP $r ...

  6. Python学习之模块基础

    模块就是程序 编写以下简单代码 print('hello python') 并将py文件保存在c盘的python(假设新建)文件下,通过pycharm的Terminal 或者windom命令窗口调出p ...

  7. Ruby字符串的一些方法

    最近因为公司需求开始看ruby,先从ruby的基本数据类型开始看 看到ruby的字符串类型string,发现ruby中的字符串单双引号是不一样的,这点和Python有那么点不一样 主要是我们对字符串进 ...

  8. RHCE7认证学习笔记17——KickStart安装系统

    一.自动化安装系统工具 1.Cobbler    另一个自动化安装工具: 2.Kickstart 二.使用kickstart自动化安装系统 服务器安装的软件: 1.dhcp服务   [root@lin ...

  9. stm32--FatFs移植(SPIFlash)

    前言 硬件: 单片机:stm32f072CB,sram大小16k.(其他单片机只要sram>8k即可通用) SPIFlash:W25Q128FV,16Mbyte,单次擦除最小4k. 程序使用Ke ...

  10. http报文和浏览器缓存机制

    目录 1. 请求报文 1.1请求行 1.2 请求头 一些常用的请求头信息 2. 响应报文 2.1 状态行 1> 响应状态码 2> 常见的响应状态码 2.2 响应头 3. 浏览器缓存 3.1 ...