- 浏览: 422172 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (170)
- java (77)
- javascript (5)
- jsp (1)
- servlet (6)
- struts (8)
- hibernate (3)
- spring (4)
- ajax (5)
- jquery (3)
- apache cxf (0)
- ext.js (1)
- hadoop (0)
- android (0)
- html5 (2)
- linux (5)
- flex (1)
- tomcat (1)
- jboss (0)
- nginx (0)
- mysql (16)
- sql server (3)
- oracle (4)
- div+css (0)
- mybatis (4)
- design patterns (22)
- xml (2)
- postgresql (3)
- velocity (1)
- freemarker (1)
- kendo-ui (2)
- ibatis (1)
- socket (1)
- C and C++ (1)
- C# (2)
- 程序设计----算法 (0)
- jersey (1)
- dd (0)
- perl (1)
- shell (0)
最新评论
-
书策稠浊:
兄弟,这tm是Java?
java调用百度地图和谷歌地图 -
fengyunlouyanyu:
jquery----删除指定id的div下的img -
yangjianzhouctgu:
Neoman 写道hi,我看你引入了kendo.web.min ...
kendo-ui中kendoGrid的用法 -
Neoman:
hi,我看你引入了kendo.web.min.js 这个js, ...
kendo-ui中kendoGrid的用法 -
yangjianzhouctgu:
llscp 写道这是JS吧...对的呀
java调用百度地图和谷歌地图
面试过程中,多线程被问到的概率非常大,差不多都会问的。
下面从线程安全概念、什么情况下会产生多线程安全问题、多线程问题的原因、多线程问题的解决方法、java对多线程的支持、例子等方面来总结多线程。
1、线程安全概念
线程运行过程中,对共享对象的访问和预期或理论上的值有差别,这时就产生了线程安全问题,下面的例子就是三个线程对变量num产生了并发访问。
输出结果:有时为0,有时为10,有时为20.
输出结果的期望值是10,这时就产生了多线程的安全问题,这里有三个线程:t1、t2、main线程同时对num进行访问(读取和设值),这个变量num在这个多线程环境下就是不安全的。
2.什么情况下会产生多线程安全问题
上面我们已经通过一个例子展示了多线程的安全问题了,那么什么情况下产生多线程的安全问题呢?
多个线程对同一个对象的并发访问(读取和设值),这时就有可能产生多线程安全问题。可能是一个线程在读取共享变量值的时候,另外一个线程已经改变了这个变量的值了,这时候读取的值就不是预期的值了,这就产生了多线程安全问题了。
3.多线程问题的原因
多线程产生的原因看似很简单,但是要弄懂还得从线程执行原理上分析。
上图中展示了两个线程对一个共享变量的存储访问。线程在执行时,首先会将主内存区的共享变量拷贝一个副本到自己的工作线程区,执行的过程中,只会对自己工作线程区中的副本进行操作,什么时候讲共享变量的副本同步到主内存区是不确定的,拿1中的例子来说吧,线程t1执行完后(循环执行完)把num副本同步到主内存,在这之前,其他线程(t2和main线程都没同步主内存num的值),这时,主内存的值就是10,由于线程执行的不确定性,假设线程t1和t2开始时都把num的值读取到自己的工作区,然后t1执行,直到结束,把工作内存的num值同步到主内存,这时线程t2的工作区num副本的值为0,然后t2执行,直到完成,然后同步主内存num的值,这时num的值被覆盖为10,而不是期望的20.这就是多线程并发存储对象产生线程安全问题的实质。
4.多线程问题的解决方法
多线程安全问题产生了,就需要找到解决方案,我们已经知道了多线程安全问题的实质,线程读取了共享变量错误的值,或者线程设置了共享变量的值而没有及时写入主内存。这里有对象锁、可重入锁、读写锁、信号量等措施来防止多线程安全问题。
5.java对多线程的支持
java中有关键字final、synchronized、java.util.concurrent包及其子包下面的类都对多线程提供了支持。
volatile不能保证线程安全,这个关键字只能保证变量的可见性和防止指令重排序。
final关键字修饰的变量表示该变量的值不能被改变,当然,但这个关键之被用来修饰一个独享变量的时候,只能保证对象变量在内存中的地址不可以变,而无法保证这个对象中包含的值的被改变。
synchronized 这个关键字只能用来修饰方法,由于每个对象都有一个内部锁,当一个线程进入一个对象的一个synchronized方法中后,就获得了这个对象的内部锁,就去主内存读取共享变量的值(synchronized关键字语法要求),其他线程就无法获取这个对象的内部锁了,只能处于等待状态,当获得内部锁的线程执行完这个方法后,退出方法时,就会讲共享变量值同步到主内存,这时synchronized关键字强制执行的,这时就会释放掉内部锁,其他线程处于等待的线程就会获取这个对象内部锁,进行方法执行,这时该线程工作区的变量值已经是最新的了,因此线程可以安全的执行了。
java.util.concurrent下面的类用到了可重入锁、读写锁和CAS(compare and swap,这连个操作被设计成一条指令,用到了乐观锁机制)执行。
6.生产者消费者例子
队列大小为2,两个生产者,一个消费者,因此生产者一般都处于阻塞状态,队列一般都处于满的状态。
下面从线程安全概念、什么情况下会产生多线程安全问题、多线程问题的原因、多线程问题的解决方法、java对多线程的支持、例子等方面来总结多线程。
1、线程安全概念
线程运行过程中,对共享对象的访问和预期或理论上的值有差别,这时就产生了线程安全问题,下面的例子就是三个线程对变量num产生了并发访问。
package com.yangjianzhou.multiThread.test; public class ThreadUnsafeTest { public static int num = 0; public static void main(String[] args) { Thread t1 = new Thread(new SubRunnable()); Thread t2 = new Thread(new SubRunnable()); t1.start(); t2.start(); System.out.println(num); } static class SubRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 10; i++) { num++; } } } }
输出结果:有时为0,有时为10,有时为20.
输出结果的期望值是10,这时就产生了多线程的安全问题,这里有三个线程:t1、t2、main线程同时对num进行访问(读取和设值),这个变量num在这个多线程环境下就是不安全的。
2.什么情况下会产生多线程安全问题
上面我们已经通过一个例子展示了多线程的安全问题了,那么什么情况下产生多线程的安全问题呢?
多个线程对同一个对象的并发访问(读取和设值),这时就有可能产生多线程安全问题。可能是一个线程在读取共享变量值的时候,另外一个线程已经改变了这个变量的值了,这时候读取的值就不是预期的值了,这就产生了多线程安全问题了。
3.多线程问题的原因
多线程产生的原因看似很简单,但是要弄懂还得从线程执行原理上分析。
上图中展示了两个线程对一个共享变量的存储访问。线程在执行时,首先会将主内存区的共享变量拷贝一个副本到自己的工作线程区,执行的过程中,只会对自己工作线程区中的副本进行操作,什么时候讲共享变量的副本同步到主内存区是不确定的,拿1中的例子来说吧,线程t1执行完后(循环执行完)把num副本同步到主内存,在这之前,其他线程(t2和main线程都没同步主内存num的值),这时,主内存的值就是10,由于线程执行的不确定性,假设线程t1和t2开始时都把num的值读取到自己的工作区,然后t1执行,直到结束,把工作内存的num值同步到主内存,这时线程t2的工作区num副本的值为0,然后t2执行,直到完成,然后同步主内存num的值,这时num的值被覆盖为10,而不是期望的20.这就是多线程并发存储对象产生线程安全问题的实质。
4.多线程问题的解决方法
多线程安全问题产生了,就需要找到解决方案,我们已经知道了多线程安全问题的实质,线程读取了共享变量错误的值,或者线程设置了共享变量的值而没有及时写入主内存。这里有对象锁、可重入锁、读写锁、信号量等措施来防止多线程安全问题。
5.java对多线程的支持
6.生产者消费者例子
队列大小为2,两个生产者,一个消费者,因此生产者一般都处于阻塞状态,队列一般都处于满的状态。
生产者: package com.yangjianzhou.multiThread.test; import java.util.concurrent.BlockingQueue; public class Producer implements Runnable { private BlockingQueue<String> queue; public Producer(BlockingQueue<String> queue) { this.queue = queue; } @Override public void run() { try { for (int i = 0; i < 10; i++) { System.out.println("Producer "+Thread.currentThread().getName()+" , queue.size = "+queue.size()); queue.put("break" + Thread.currentThread().getName() + i); } } catch (Exception e) { } } } 消费者: package com.yangjianzhou.multiThread.test; import java.util.concurrent.BlockingQueue; public class Customer implements Runnable { private BlockingQueue<String> queue; public Customer(BlockingQueue<String> queue) { this.queue = queue; } @Override public void run() { try { for (int i = 0; i < 10; i++) { System.out.println("customer "+Thread.currentThread().getName()+" , queue.size = "+queue.size()); queue.take(); } } catch (Exception e) { } } } 测试程序: package com.yangjianzhou.multiThread.test; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public class Test { public static void main(String[] args) { BlockingQueue<String> queue = new ArrayBlockingQueue<String>(2); Thread customer = new Thread(new Customer(queue)); Thread producer1 = new Thread(new Producer(queue)); Thread producer2 = new Thread(new Producer(queue)); customer.start(); producer1.start(); producer2.start(); } } 运行结果: customer Thread-0 , queue.size = 0 Producer Thread-1 , queue.size = 0 Producer Thread-2 , queue.size = 1 Producer Thread-2 , queue.size = 2 Producer Thread-1 , queue.size = 2 Producer Thread-2 , queue.size = 2 customer Thread-0 , queue.size = 1 customer Thread-0 , queue.size = 2 Producer Thread-1 , queue.size = 2 Producer Thread-2 , queue.size = 2 customer Thread-0 , queue.size = 1 Producer Thread-1 , queue.size = 2 customer Thread-0 , queue.size = 2 customer Thread-0 , queue.size = 2 Producer Thread-2 , queue.size = 2 customer Thread-0 , queue.size = 2 Producer Thread-1 , queue.size = 2 customer Thread-0 , queue.size = 1 Producer Thread-2 , queue.size = 2 Producer Thread-1 , queue.size = 2 customer Thread-0 , queue.size = 2 customer Thread-0 , queue.size = 1 Producer Thread-2 , queue.size = 2 Producer Thread-1 , queue.size = 2
发表评论
-
spring boot应用测试框架介绍
2018-07-19 14:44 701个人原创博客:spring boot应用测试框架介绍 -
可执行jar包的配置与运行
2017-06-04 19:42 964spring boot项目可以以jar包的形式执行运行。s ... -
多线程并发
2016-05-21 23:49 0Splitter.on('|').trimResults(). ... -
jdk动态代理实现原理
2016-05-09 23:12 719jdk的动态代理即使用反射来实现,具体由Proxy、Invoc ... -
spring常见注解
2016-05-01 23:33 11821.Autowired 通过spring的依赖注入功能来 ... -
spring常见配置作用
2016-04-29 23:08 894一般应用中常见spring的 ... -
数据来自两个系统时的内存分页算法
2016-04-24 23:12 788业务数据来自a-app与b-app,其中a-app中数据的业务 ... -
linux下java web开发环境搭建
2016-04-10 14:09 1098一般的java web开发涉及到的开发工具有:jdk、tomc ... -
linux下md5sum和DigestUtils.md5Hex的关系
2015-12-19 22:30 8447本文对linux下md5sum命令和java中DigestUt ... -
基于jersey的web service
2015-11-22 22:55 971本文是基于jersey的web service 的两个小例子, ... -
面试总结----spring
2015-05-19 22:17 870spring在面试中经常被 ... -
面试总结----java虚拟机
2015-05-17 23:20 715在面试过程中,java虚拟机被问到的概率非常大,应该是每场面试 ... -
面试总结----java集合
2015-05-17 11:57 631春节刚过,打算换一份工作,于是就开始了一段准备面试的生活,准备 ... -
json串与对象之间转换的几种实现方式
2015-01-24 18:56 1836这里使用了gson,fastjson,jackson,json ... -
google关于事件的生产者消费者模式实现例子
2015-01-24 11:28 928google使用生产者/消费者模式实现了事件的产生传播处理过程 ... -
图形化显示---冒泡排序
2014-12-05 22:17 877代码: package com.thread.singal ... -
多线程----wait/notify
2014-11-06 22:06 652线程同步:两个线程依次对同一变量进行操作。 packag ... -
多线程-----阻塞队列
2014-11-05 22:43 807使用一个线程将一个指定目录下面的所有文件放在一个阻塞队列中,用 ... -
迷宫的最短路径
2014-08-19 00:31 3731代码如下: package com.chapterO ... -
深度优先遍历------部分和问题
2014-08-15 20:15 476代码如下: package com.chapterO ...
相关推荐
Java多线程-知识点梳理和总结-超详细-面试知识点.docx
大数据面试复习---Java基础---集合类、多线程、JVM 大数据面试复习----常问问题分析 大数据面试复习----画重点----思维导图 大数据面试复习----简历编写 大数据面试复习----练习的面试题+笔试题 大数据面试复习----...
JVM 的运行机制 多线程 JVM 的内存区域 JVM 会创建操作系统的接口创建一个原生线程。JVM 线程和操作系统线程是一一对应的
01大数据面试复习----Java基础---集合类、多线程、JVM 02大数据面试复习----画重点----常问问题分析 03大数据面试复习----画重点----精心制作热门技术思维导图 04大数据面试复习----画重点----56家+真实互联网大公司...
个人总结40个Java多线程面试问题和答案,很全面,让你不再担心多线程的面试问题。
2020面试题总结多线程篇.pdf
java面试-BIO,NIO,AIO,Netty面试题 35道 java面试-Java+最常见的+200++面试题汇总+答案总结汇总 java面试-Java并发编程最全面试题 123道 ...java面试-多线程面试59题(含答案) java面试-设计模式面试题 14道
1、面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: ...总共90多道题目,包含面向对象、算法、多线程等面试题及详解 大厂面试题集,纯人工手写,分享不易,有问题敬请谅解 。。。。。。。。
最新java面试关于多线程,锁,同步相关知识总结
多线程面试题小小总结一下
该文档是我总结的c++笔试面试通常会问的一些问题。另外可以从我的资源目录下找c++数据结构与算法,c++笔试面试基础两部分材料,综合这三个材料一起看,我相信大家一定尽快找到工作。
9.StringBuffer和StringBuilder的区别?(实际面试题) 1.在执行速度方面的比较:StringBuilder 快于 StringBuffer 2. StringBuffer与StringBuilder,他们是...多线程操作字符串缓冲区下操作大量数据=StringBuffer
Spring使用与实现总结.pdf Spring源码解析.pdf Tomcat源码解析.pdf 面试---1. Java&设计模式.pdf 面试---2. Java集合.pdf 面试---3. Java并发.pdf 面试---4. JVM&Linux.pdf 面试---5. JavaWeb&HTTP&安全&Git...
JAVA多线程(精典总结) 面试 大全 java
各大公司校招笔试面试多线程和并发历年真题总结,总共上百页吧。其他类目可以查看我上传的资源
对java多线程相关问题进行了总结。很多核心Java面试题来源于多线程(Multi-Threading)和集合框架(Collections Framework),理解核心线程概念时,娴熟的实际经验是必需的。这篇文章收集了 Java 线程方面一些典型的问题...
针对高并发、JVM、GC大厂面试+详细解答总结汇总(对多线程、锁机制、内存分配、垃圾回收算法等,有这详细易懂的讲解!)
C++面试题 1.是不是一个父类写了一个virtual 函数,如果子类覆盖它的函数不加virtual ,也能实现多态? virtual修饰符会被隐形继承的。 private 也被集成,只事派生类没有访问权限而已 virtual可加可不加 子类的...
收集了 Java 线程方面一些典型的问题,这些问题经常被高级工程师所问到。这篇文章收集了 Java 线程方面一些典型的问题,这些问题经常被高级工程师所问到。
Java核心技术:如多线程、网络编程、序列化等都有详细的解释和示例。 常用框架:如Spring、MyBatis等框架的使用方法和内部原理都有涉及。 数据库相关:包括关系型数据库和非关系型数据库的使用,以及JDBC、MyBatis等...