- 浏览: 428522 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (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 749个人原创博客:spring boot应用测试框架介绍 -
可执行jar包的配置与运行
2017-06-04 19:42 1006spring boot项目可以以jar包的形式执行运行。s ... -
多线程并发
2016-05-21 23:49 0Splitter.on('|').trimResults(). ... -
jdk动态代理实现原理
2016-05-09 23:12 773jdk的动态代理即使用反射来实现,具体由Proxy、Invoc ... -
spring常见注解
2016-05-01 23:33 12321.Autowired 通过spring的依赖注入功能来 ... -
spring常见配置作用
2016-04-29 23:08 933一般应用中常见spring的 ... -
数据来自两个系统时的内存分页算法
2016-04-24 23:12 842业务数据来自a-app与b-app,其中a-app中数据的业务 ... -
linux下java web开发环境搭建
2016-04-10 14:09 1134一般的java web开发涉及到的开发工具有:jdk、tomc ... -
linux下md5sum和DigestUtils.md5Hex的关系
2015-12-19 22:30 8519本文对linux下md5sum命令和java中DigestUt ... -
基于jersey的web service
2015-11-22 22:55 1006本文是基于jersey的web service 的两个小例子, ... -
面试总结----spring
2015-05-19 22:17 910spring在面试中经常被 ... -
面试总结----java虚拟机
2015-05-17 23:20 740在面试过程中,java虚拟机被问到的概率非常大,应该是每场面试 ... -
面试总结----java集合
2015-05-17 11:57 675春节刚过,打算换一份工作,于是就开始了一段准备面试的生活,准备 ... -
json串与对象之间转换的几种实现方式
2015-01-24 18:56 1878这里使用了gson,fastjson,jackson,json ... -
google关于事件的生产者消费者模式实现例子
2015-01-24 11:28 975google使用生产者/消费者模式实现了事件的产生传播处理过程 ... -
图形化显示---冒泡排序
2014-12-05 22:17 917代码: package com.thread.singal ... -
多线程----wait/notify
2014-11-06 22:06 684线程同步:两个线程依次对同一变量进行操作。 packag ... -
多线程-----阻塞队列
2014-11-05 22:43 849使用一个线程将一个指定目录下面的所有文件放在一个阻塞队列中,用 ... -
迷宫的最短路径
2014-08-19 00:31 3761代码如下: package com.chapterO ... -
深度优先遍历------部分和问题
2014-08-15 20:15 517代码如下: package com.chapterO ...
相关推荐
针对“需求分析面试总结--深交所.zip”这个主题,我们可以深入探讨以下几个相关知识点: 1. **需求分析**:需求分析是软件工程的第一步,涉及到对用户需求的理解、记录、验证和管理。在这个过程中,分析师需要与...
"Java多线程-知识点梳理和总结-超详细-面试知识点" Java多线程是Java编程语言中最基本也是最重要的概念之一。多线程编程可以提高程序的执行效率、改善用户体验和提高系统的可扩展性。但是,多线程编程也存在一些...
大数据面试复习---Java基础---集合类、多线程、JVM 大数据面试复习----常问问题分析 大数据面试复习----画重点----思维导图 大数据面试复习----简历编写 大数据面试复习----练习的面试题+笔试题 大数据面试复习----...
这有助于在多线程环境下保证数据的一致性。 3. **不推荐使用的线程控制方法**: - `stop()`:不推荐使用,因为它会强制终止线程,可能会导致对象处于不一致的状态,进而引发不可预测的行为。 - `suspend()`:同样...
### Java私塾面试题解析 —— 线程与EJB部分...以上内容总结了Java私塾面试题中关于线程和EJB的部分,涵盖了线程的基础概念、实现方式、控制方法以及相关的高级特性,希望能帮助读者更好地理解并掌握Java中的线程编程。
JVM 的运行机制 多线程 JVM 的内存区域 JVM 会创建操作系统的接口创建一个原生线程。JVM 线程和操作系统线程是一一对应的
01大数据面试复习----Java基础---集合类、多线程、JVM 02大数据面试复习----画重点----常问问题分析 03大数据面试复习----画重点----精心制作热门技术思维导图 04大数据面试复习----画重点----56家+真实互联网大公司...
Java多线程面试问题和答案总结 Java多线程是一种高级的编程技术,能够充分发挥多核CPU的优势,防止阻塞,简化模型建立,提高程序的效率和可维护性。下面是40个Java多线程面试问题和答案的总结,涵盖了多线程的基本...
### Java多线程知识点总结及企业真题解析 #### 一、知识点总结 ##### (1)多线程相关概念 1. **程序、进程和线程的区分**: - **程序**:为了完成特定的任务而编写的指令集合。它是静态的概念。 - **进程**:...
6. **多线程** - **线程的创建**:通过实现Runnable接口或继承Thread类。 - **线程同步**:synchronized关键字保证同一时刻只有一个线程执行特定代码段,防止数据竞争。 - **线程通信**:wait()、notify()和...
java面试-BIO,NIO,AIO,Netty面试题 35道 java面试-Java+最常见的+200++面试题汇总+答案总结汇总 java面试-Java并发编程最全面试题 123道 ...java面试-多线程面试59题(含答案) java面试-设计模式面试题 14道
在C++笔试面试中,网络和多线程是两个经常被提及的重要知识点。本篇文档详细列举了关于网络部分的面试题目,同时也涉及了与多线程相关的TCP/IP协议栈的建立和断开过程。以下为详细的知识点总结: 1. TCP服务创建...
多线程面试59题(含答案)是关于多线程编程的知识点总结,涵盖了多线程的基本概念、优点、线程和进程的区别、Java 实现多线程的方式、启动线程方法的区别、终止线程的方式、线程的生命周期、wait()和 sleep()方法的...
4. **多线程与并发**:Java提供了丰富的并发工具,如synchronized关键字、volatile变量、ThreadLocal、并发集合(如ConcurrentHashMap)等,掌握这些能解决多线程环境下的同步问题。 5. **内存管理与垃圾回收**:...
面试题总结——多线程篇 一、多线程实现方式 多线程实现方式主要有四种:继承 Thread 类、实现 Runable 接口、实现 Callable 接口、通过 FutureTask 包装器。这四种方式可以满足不同的需求,例如继承 Thread 类...
1、面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: ...总共90多道题目,包含面向对象、算法、多线程等面试题及详解 大厂面试题集,纯人工手写,分享不易,有问题敬请谅解 。。。。。。。。
多线程 - **线程创建**:继承Thread类、实现Runnable接口。 - **线程同步**:synchronized关键字、ReentrantLock、Condition。 - **线程间通信**:wait()、notify()、notifyAll()。 - **并发工具类**:...
4. **多线程**: - 线程的创建方式:Thread类、实现Runnable接口。 - 线程状态:新建、就绪、运行、阻塞、终止。 - 同步机制:synchronized、wait()、notify()、notifyAll()。 5. **并发编程**: - volatile...
最新java面试关于多线程,锁,同步相关知识总结
Java 基础类库面试知识点总结 一、Java IO 流 Java 中有两种类型的流:字节流和字符流。字节流继承于 InputStream...Java 面试题包括了 Java 语言的基础知识、Java 类库、多线程、网络编程、数据库编程等方面的知识。