- 浏览: 368172 次
- 性别:
最新评论
-
天使建站:
这里这篇文章更详细 还有完整的实例演示:js跳出循环:brea ...
js跳出循环的方法区别(break,continue,return) -
jahentao:
我觉得Jcreator和eclipse中的列出属性和方法,很多 ...
反射原理 -
T240178168:
相互交流下吧
ie9以下都有这个问题(ajax) -
blackproof:
试了一下,的确第一种写法oracle优化了,效率比第二种快多了 ...
Oracle分页sql语句 -
杨白白:
进程与线程
Synchronized关键字
从1.0版本开始,Java中的每一个对象都有一个内部锁。
如果一个方法用synchronized关键字生命,那么对象的锁将保护整个方法。也就是说,要调用该方法,线程必须获得内部的对象锁。
换句话说:
public synchronized void method(){
method body
}
等价于
public void method(){
this.intrinsicLock.lock();
try{
method body
}
finally{ this.intrinsicLock.unlock();}
}
必须了解每一个对象有一个内部锁,并且该锁有一个内部条件。由锁来管理那些试图进入synchronized方法的线程,由条件来管理那些调用wait的线程。
将静态方法声明为synchronized也是合法的。如果调用这种方法,该方法获得这个类的内部锁。(注:原文里是“获得类对象的内部锁”,为了避免出现理解误差,此处改为“类的内部锁”)
例如:如果Bank类有一个静态同步的方法,那么该方法被调用时,Bank.class
的锁被锁住。因此,没有其他线程可以调用同一个类的这个或任何其他的同步静态方法。
个人备注:关键在于区别成员方法和类方法的区别。
synchronized的4种用法
1. 方法声明时使用,线程获得的是成员锁.
2. 对某一代码块使用,synchronized后跟括号,括号里是变量,线程获得的是成员锁.
3.synchronized后面括号里是一对象,此时,线程获得的是对象锁.
4.synchronized后面括号里是类,此时,线程获得的是对象锁.
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用.
Runnable封装一个异步运行的任务,可以把它想象成为一个没有参数和返回值得异步方法。
Callable和 Runnable 类似,但是有返回值。
Callable接口是一个参数化的类型,只有一个方法call。
public interface Callable<V>{
V call() throws Exception;
}
类型参数是返回值的类型。例如Callable<Integer>表示一个最终返回Integer对象的异步计算。
Future保存异步计算的结果,可以启动一个计算,将Future对象交给某个线程,然后忘掉它。Future对象的所有者在结果计算好之后就可以获得它。
public interface Future<V>{
V get() throws …;
方法被阻塞,直到计算完成。
V get(lont timeout, TimeUnit unit) throws …;
如果在计算完成之前,第二个方法的调用超时,抛出TimeoutException异常。
如果运行计算的线程被中断,则两个get方法都将抛出InterruptedException。
如果计算已经完成,那么get方法立即返回。
void cancel(boolean mayInterrupt);
使用该方法取消该计算,如果计算还未开始,它被取消且不再开始。
如果计算处于运行之中,那么如果参数为true,它就被中断。
boolean isCancelled();如果在任务正常完成前将其取消,则返回true。
boolean isDone();如果在任务已完成,则返回true。
}
public class FutureTask<V>
extends Object
implements Future<V>, Runnable
FutureTask 包装器是一种非常方便的机制,可以将Callable转换成Future 和 Runnable,它同时实现二者的接口
FutureTask(Callable<V> callable)
创建一个 FutureTask,一旦运行就执行给定的 Callable。
FutureTask(Runnable runnable, V result)
创建一个 FutureTask,一旦运行就执行给定的 Runnable,并安排成功完成时 get 返回给定的结果 。
例如:
Callable<Integer> myCall = ……..;
FutureTask<Integer> task = new FutureTask<Integer>(myCall);
Thread t = new Thread(task);// 在这里是一个Runnable
t.start();
….
Integer result = task.get(); //在这里是一个Future
构建一个新的线程是有一定代价的,因为涉及与操作系统的交互。如果程序中创建了大量的生命期很短的线程,应该使用线程池(thread pool).
一个线程池中包含许多准备运行的空闲线程,将Runnable对象交给线程池,就会有一个线程调用run方法。当run方法退出时,线程不会死亡,而是在池中准备为下一个请求提供服务。
另一个使用线程池的理由是减少并发线程的数目。创建大量线程会大大降低性能甚至使虚拟机崩溃。如果有一个会创建许多线程的算法,应该使用一个线程数“固定的”线程池以限制并发线程的总数。
java.util.concurrent
接口 Executor
所有已知子接口:
ExecutorService, ScheduledExecutorService
所有已知实现类:
AbstractExecutorService, ScheduledThreadPoolExecutor, ThreadPoolExecutor
执行器类(Executor)类有许多静态工厂方法用来构建线程池。java.util.concurrent.Executors
public class Executorsextends Object
ExecutorService newCachedThreadPool()
返回一个带缓存的线程池,该池在必要时创建新线程;空闲线程会被保留60秒
ExecutorService newFixedThreadPool(int size)
返回一个线程池,该池包含固定数量的线程;空闲线程会一支被保留
ExecutorService newSingleThreadExecutor
只有一个线程的“池”,该线程顺序执行每一个提交的任务
这三个方法返回实现了ExecutorService接口的ThreadPoolExecutor类的对象。
Java.util.concurrent.ExecutorService
可用下面的方法之一将一个Runnable对象或Callable对象提交给ExecutorService:
Future<?> submit(Runnable task)
返回一个Future<?>可以使用这样的一个对象来调用isDone、cancel或isCancelled。但是,get方法在完成的时候只是简单的返回null。
Future<T> submit(Runnable task, T result)
返回的Future<T>的get方法在完成的时候返回指定的result对象。
Future<T> submit(Callable<T> task)
返回的Future对象将在计算结果准备好的时候得到它。
sutdown()
当用完一个线程池的时候,调用shutdown()方法方法启动该池的关闭序列,被关闭的执行器不再接受新的任务。当所有任务都完成以后,线程池中的线程死亡。
shutdownNow()
该方法取消尚未开始的的所有任务并试图中断正在运行的线程。
下面总结在使用线程池时应该做的事:
调用Executors类中静态的方法 newCachedThreadPool或..
调用submit提交Runnable 或Callable对象
如果想要取消一个任务,或如果提交Callable对象,那就需要保存好返回的Future对象
当不需要提交任何任务时,调用shutdown。
补充:
ScheduleExecutorService newScheduledThreadPool(int size)
用于预定执行而构建的固定线程池,替代java.util.Timer ( Timer用于安排以后
在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。)
ScheduleExecutorService newSingleThreadScheduleExecutor()用于预定执行而构建的单线程“池”
从1.0版本开始,Java中的每一个对象都有一个内部锁。
如果一个方法用synchronized关键字生命,那么对象的锁将保护整个方法。也就是说,要调用该方法,线程必须获得内部的对象锁。
换句话说:
public synchronized void method(){
method body
}
等价于
public void method(){
this.intrinsicLock.lock();
try{
method body
}
finally{ this.intrinsicLock.unlock();}
}
必须了解每一个对象有一个内部锁,并且该锁有一个内部条件。由锁来管理那些试图进入synchronized方法的线程,由条件来管理那些调用wait的线程。
将静态方法声明为synchronized也是合法的。如果调用这种方法,该方法获得这个类的内部锁。(注:原文里是“获得类对象的内部锁”,为了避免出现理解误差,此处改为“类的内部锁”)
例如:如果Bank类有一个静态同步的方法,那么该方法被调用时,Bank.class
的锁被锁住。因此,没有其他线程可以调用同一个类的这个或任何其他的同步静态方法。
个人备注:关键在于区别成员方法和类方法的区别。
synchronized的4种用法
1. 方法声明时使用,线程获得的是成员锁.
2. 对某一代码块使用,synchronized后跟括号,括号里是变量,线程获得的是成员锁.
3.synchronized后面括号里是一对象,此时,线程获得的是对象锁.
4.synchronized后面括号里是类,此时,线程获得的是对象锁.
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用.
Runnable封装一个异步运行的任务,可以把它想象成为一个没有参数和返回值得异步方法。
Callable和 Runnable 类似,但是有返回值。
Callable接口是一个参数化的类型,只有一个方法call。
public interface Callable<V>{
V call() throws Exception;
}
类型参数是返回值的类型。例如Callable<Integer>表示一个最终返回Integer对象的异步计算。
Future保存异步计算的结果,可以启动一个计算,将Future对象交给某个线程,然后忘掉它。Future对象的所有者在结果计算好之后就可以获得它。
public interface Future<V>{
V get() throws …;
方法被阻塞,直到计算完成。
V get(lont timeout, TimeUnit unit) throws …;
如果在计算完成之前,第二个方法的调用超时,抛出TimeoutException异常。
如果运行计算的线程被中断,则两个get方法都将抛出InterruptedException。
如果计算已经完成,那么get方法立即返回。
void cancel(boolean mayInterrupt);
使用该方法取消该计算,如果计算还未开始,它被取消且不再开始。
如果计算处于运行之中,那么如果参数为true,它就被中断。
boolean isCancelled();如果在任务正常完成前将其取消,则返回true。
boolean isDone();如果在任务已完成,则返回true。
}
public class FutureTask<V>
extends Object
implements Future<V>, Runnable
FutureTask 包装器是一种非常方便的机制,可以将Callable转换成Future 和 Runnable,它同时实现二者的接口
FutureTask(Callable<V> callable)
创建一个 FutureTask,一旦运行就执行给定的 Callable。
FutureTask(Runnable runnable, V result)
创建一个 FutureTask,一旦运行就执行给定的 Runnable,并安排成功完成时 get 返回给定的结果 。
例如:
Callable<Integer> myCall = ……..;
FutureTask<Integer> task = new FutureTask<Integer>(myCall);
Thread t = new Thread(task);// 在这里是一个Runnable
t.start();
….
Integer result = task.get(); //在这里是一个Future
构建一个新的线程是有一定代价的,因为涉及与操作系统的交互。如果程序中创建了大量的生命期很短的线程,应该使用线程池(thread pool).
一个线程池中包含许多准备运行的空闲线程,将Runnable对象交给线程池,就会有一个线程调用run方法。当run方法退出时,线程不会死亡,而是在池中准备为下一个请求提供服务。
另一个使用线程池的理由是减少并发线程的数目。创建大量线程会大大降低性能甚至使虚拟机崩溃。如果有一个会创建许多线程的算法,应该使用一个线程数“固定的”线程池以限制并发线程的总数。
java.util.concurrent
接口 Executor
所有已知子接口:
ExecutorService, ScheduledExecutorService
所有已知实现类:
AbstractExecutorService, ScheduledThreadPoolExecutor, ThreadPoolExecutor
执行器类(Executor)类有许多静态工厂方法用来构建线程池。java.util.concurrent.Executors
public class Executorsextends Object
ExecutorService newCachedThreadPool()
返回一个带缓存的线程池,该池在必要时创建新线程;空闲线程会被保留60秒
ExecutorService newFixedThreadPool(int size)
返回一个线程池,该池包含固定数量的线程;空闲线程会一支被保留
ExecutorService newSingleThreadExecutor
只有一个线程的“池”,该线程顺序执行每一个提交的任务
这三个方法返回实现了ExecutorService接口的ThreadPoolExecutor类的对象。
Java.util.concurrent.ExecutorService
可用下面的方法之一将一个Runnable对象或Callable对象提交给ExecutorService:
Future<?> submit(Runnable task)
返回一个Future<?>可以使用这样的一个对象来调用isDone、cancel或isCancelled。但是,get方法在完成的时候只是简单的返回null。
Future<T> submit(Runnable task, T result)
返回的Future<T>的get方法在完成的时候返回指定的result对象。
Future<T> submit(Callable<T> task)
返回的Future对象将在计算结果准备好的时候得到它。
sutdown()
当用完一个线程池的时候,调用shutdown()方法方法启动该池的关闭序列,被关闭的执行器不再接受新的任务。当所有任务都完成以后,线程池中的线程死亡。
shutdownNow()
该方法取消尚未开始的的所有任务并试图中断正在运行的线程。
下面总结在使用线程池时应该做的事:
调用Executors类中静态的方法 newCachedThreadPool或..
调用submit提交Runnable 或Callable对象
如果想要取消一个任务,或如果提交Callable对象,那就需要保存好返回的Future对象
当不需要提交任何任务时,调用shutdown。
补充:
ScheduleExecutorService newScheduledThreadPool(int size)
用于预定执行而构建的固定线程池,替代java.util.Timer ( Timer用于安排以后
在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。)
ScheduleExecutorService newSingleThreadScheduleExecutor()用于预定执行而构建的单线程“池”
发表评论
-
UML类图与类的关系详解-UML一波流系列
2016-12-11 20:23 683http://peterwei.iteye.com/blog/ ... -
201612-8笔记
2016-12-08 22:46 590数据库设计 1.主表明确 主表一直是主,里面不需要关联关系 ... -
OOP和AOP区别
2015-04-27 17:18 3436OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行 ... -
正则表达式的基础语法
2015-01-06 23:08 810首先让我们看两个特殊 ... -
Filter过滤器在Web.xml中几个标签说明
2015-01-06 22:58 1675<!-- 定义Filter --> <fi ... -
JSP中out.print 和 out.write 区别
2015-01-06 22:55 1690jsp中的out对象是JspWriter类型的.而JspWri ... -
使用Eclipse开发Java Web过程中Debug调试的使用方法
2014-03-06 21:35 1664这里介绍的是在Eclipse中的Debug调试。 首先右击 ... -
iBATIS CDATA
2014-02-27 23:52 863在ibatis 中,SQL语句经常会出现一些特殊符号,比如:& ... -
isNotEmpty isNotNull
2014-01-27 14:20 1532ibatis : isNotEmpty:过滤空串"& ... -
读书:《代码整洁之道》
2014-01-17 00:10 12231. 本书内容概要 核心观 ... -
String,StringBuffer和StringBuild性能
2014-01-08 22:09 977在不考虑线程安全的前 ... -
stringbuffer 的缓冲长度
2014-01-08 22:06 14351 StringBuffer缓冲长度,或者叫容量会随着 ... -
重构——代码的坏味道
2014-01-04 00:17 878重构——代码的坏味道 1. Duplicated Code(重 ... -
xls与csv文件是什么区别?功能和作用上有什么不同
2013-11-03 22:30 197401 xls 文件就是Microsoft e ... -
toString() ,String,String.valueOf
2013-07-20 00:52 2498常用的方法有Object#toString(),(String ... -
jre与jdk的区别
2013-07-20 00:48 2586JDK就是Java Development Kit. ... -
Java编译原理
2013-01-22 21:11 1885Java编译原理 1. 关于动 ... -
JVM的基本工作原理和特点
2013-01-22 21:08 1340JVM的基本工作原理和特点 操作系统装入jvm是通过jd ... -
Math的属性之对数
2013-01-22 11:20 1582Math.LN2 2的自然对数 Math.LN10 10的自然 ... -
面试题50
2013-01-14 23:37 1438【程序1】 题目:古典问题:有一对兔子,从出生后第3个月起 ...
相关推荐
synchronized 关键字是 Java 中的一个关键字,用于声明同步方法或同步块。synchronized 关键字可以确保在同一时刻只有一个线程可以访问共享资源。 Lock 接口 Lock 接口是 Java 中的一个接口,提供了 lock() 方法和...
在探讨多线程异常处理之前,首先要了解Java中的线程模型以及异常处理的基本概念。...程序员需要根据具体情况合理地使用try-catch-finally语句以及synchronized关键字,并在必要时对线程池中任务的异常进行监控与处理。
synchronized关键字可以用来修饰方法或代码块,确保在同一个时刻只有一个线程可以访问该资源。 9. deadlock是什么? deadlock是多线程编程中的一种错误,发生在两个或多个线程之间的资源竞争问题。deadlock可能会...
Java提供了两种方式实现线程同步机制,分别是使用synchronized关键字和java.util.concurrent.locks.Lock接口。 线程池的应用: 线程池技术可以应用于Web服务系统中,控制服务器系统的最大并发数与最多处理的任务数...
在Java程序中,创建线程有四种方式:继承Thread类、实现Runnable接口、使用Callable接口和使用线程池。其中,继承Thread类和实现Runnable接口是最常用的两种方式。 线程的生命周期包括五种基本状态:新建状态、就绪...
为了确保特定线程的执行顺序,我们可以使用synchronized关键字进行同步控制,或者使用Lock接口提供的锁机制。 Java中的Callable接口类似于Runnable,但Callable可以有返回值和抛出异常。Future接口用于表示Callable...
2. 同步与互斥:为了保证数据的一致性和完整性,Java提供了多种同步机制,如synchronized关键字、wait()、notify()和notifyAll()方法,以及Lock接口(如ReentrantLock)和Condition接口。 二、Java多线程实现 1. ...
在Java程序中,多线程的运行安全可以通过使用synchronized关键字、Lock类、volatile关键字、CAS操作等实现。同时,Java也提供了线程池、Executor框架等机制来管理线程的创建和执行。 下面是Java并发编程面试题的...
- 同步机制:Java提供了`synchronized`关键字和`volatile`关键字来处理线程间的数据共享问题,避免数据不一致。 2. **Java 多线程与并发编程总结** - 并发编程是多线程的一种高级形式,它涉及到如何管理多个线程...
另一个关键概念是ReentrantLock,这是一种可重入的互斥锁,它提供了与synchronized关键字类似的功能。ReentrantLock比synchronized提供了更灵活的操作,包括尝试非阻塞地获取锁、可中断地获取锁以及超时获取锁等。...
Java提供了synchronized关键字以及Lock接口来实现线程同步,确保在特定时刻只有一个线程能访问共享资源。 接下来,我们聊聊线程池。线程池是多线程编程中的高效工具,它可以预先创建一定数量的线程,避免频繁地创建...
8. **并发控制**:在多线程环境下,使用`synchronized`关键字、Locks(如ReentrantLock)进行同步控制,防止数据竞争问题。 9. **异常处理**:在多线程环境中,正确处理异常,避免因单个线程异常导致整个程序崩溃。...
接着,作者探讨了高级并发工具的使用,这些工具能够帮助开发者更有效地管理和协调并发任务,比如使用Future和Callable接口来处理异步计算结果,以及使用ExecutorService进行线程池管理。 书中还深入讨论了并发集合...
下面将详细介绍同步的基本概念、synchronized关键字的使用以及原子数据和监控机制等内容。 ##### 1.1 概述 多线程程序设计相比单线程程序设计更为复杂,主要因为多个线程可能同时访问共享资源,从而引发数据一致性...
Java提供了synchronized关键字、Lock接口(如ReentrantLock)以及各种并发容器(如ConcurrentHashMap)来保证线程安全。 10. **线程池的最佳实践** - 核心线程数应根据系统资源和业务需求设定,一般可设为CPU核心...
线程同步:synchronized关键字、锁(Lock接口)、原子变量等。 线程池及并发包:Executors、ForkJoinPool、CountDownLatch、CyclicBarrier等。 并发优化:CAS、无锁编程、AQS原理等。 内容不限于这些,适合中、大厂...
看完《think in java》多线程章节,自己写的多线程文档,还结合了其他的相关网络资料。 线程 一. 线程池 1)为什么要使用线程池 2 2)一个具有线程池的工作队列 3 ...1)ReentrantLock和synchronized关键字的区别 41
Java提供了多种同步工具,如synchronized关键字、wait()、notify()和notifyAll()方法,以及Lock接口(如ReentrantLock)和Condition接口。synchronized关键字可以保证在同一时刻只有一个线程访问特定的代码块,防止...
此外,还可以使用Callable和FutureTask以及线程池等高级技术。 #### 线程安全与同步 线程安全是指当多个线程访问某个类(对象或方法)时,这个类始终能表现出正确的行为。Vector和SimpleDateFormat是线程安全类的...