Java线程:线程安全类和Callable与Future(有返回值的线程)
2015-12-27 20:14
549 查看
[b]一、线程安全类[/b]
当一个类已经很好的同步以保护它的数据时,这个类就称为线程安全的。当一个集合是安全的,有两个线程在操作同一个集合对象,当第一个线程查询集合非空后,删除集合中所有元素的时候,第二个线程也来执行与第一个线程相同的操作,也许第一个线程查询后,第二个也查出非空,但是此时明显是不对的。如:
虽然集合对象private List nameList=Collections.synchronizedList(new LinkedList())是同步的,但是程序并不是线程安全的。
原因是:一个线程操作列表的过程无法阻止另一个线程对列表的其他操作。解决办法是:在操作集合对象的NameList上面做一个同步。改写后的代码为:
此时,一个线程访问其中一个方法时,其他线程等待。
[b]二、Callable与Future[/b]
通过实现Callable接口实现有返回值的任务,与Runnable接口处理无返回值的任务类似。
执行了Callable任务后,可以获得一个Future对象,在该对象上调用get就可以获得Callable任务返回的Object了。如:
View Code
当一个类已经很好的同步以保护它的数据时,这个类就称为线程安全的。当一个集合是安全的,有两个线程在操作同一个集合对象,当第一个线程查询集合非空后,删除集合中所有元素的时候,第二个线程也来执行与第一个线程相同的操作,也许第一个线程查询后,第二个也查出非空,但是此时明显是不对的。如:
public class NameList { private List nameList = Collections.synchronizedList(new LinkedList()); public void add(String name) { nameList.add(name); } public String removeFirst() { if (nameList.size() > 0) { return (String) nameList.remove(0); } else { return null; } } }
public class Test { public static void main(String[] args) { final NameList nl = new NameList(); nl.add("aaa"); class NameDropper extends Thread{ public void run(){ String name = nl.removeFirst(); System.out.println(name); } } Thread t1 = new NameDropper(); Thread t2 = new NameDropper(); t1.start(); t2.start(); } }
虽然集合对象private List nameList=Collections.synchronizedList(new LinkedList())是同步的,但是程序并不是线程安全的。
原因是:一个线程操作列表的过程无法阻止另一个线程对列表的其他操作。解决办法是:在操作集合对象的NameList上面做一个同步。改写后的代码为:
public class NameList { private List nameList = Collections.synchronizedList(new LinkedList()); public synchronized void add(String name) { nameList.add(name); } public synchronized String removeFirst() { if (nameList.size() > 0) { return (String) nameList.remove(0); } else { return null; } } }
此时,一个线程访问其中一个方法时,其他线程等待。
[b]二、Callable与Future[/b]
通过实现Callable接口实现有返回值的任务,与Runnable接口处理无返回值的任务类似。
执行了Callable任务后,可以获得一个Future对象,在该对象上调用get就可以获得Callable任务返回的Object了。如:
package Thread; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class CallableTest { public static void main(String[] args)throws ExecutionException,InterruptedException{ ExecutorService pool=Executors.newFixedThreadPool(2); Callable c1=new MyCallable("A"); Callable c2=new MyCallable("B"); Future f1=pool.submit(c1); Future f2=pool.submit(c2); System.out.println(">>>"+f1.get().toString()); System.out.println(">>>"+f2.get().toString()); pool.shutdown(); } } class MyCallable implements Callable{ private String oid; MyCallable(String oid){ this.oid=oid; } public Object call()throws Exception{ return oid+"任务返回的内容"; } }
View Code
>>>A任务返回的内容 >>>B任务返回的内容
相关文章推荐
- java web基础 --- forEach标签
- [图说Java](2)Java中字符串为什么是不可变的
- SpringMVC Controller接收前台ajax的GET或POST请求返回各种参数
- Spring配置文件详解:<context:annotation-config/>和<context:component-scan base-package=""/>和<mvc:annotation-driven />
- spring mvc下shiro的session,request等问题
- LinkedList分析
- Java的安装及环境变量的配置
- for循环中i=0与i=arr.length容易被忽视的bug
- 最大熵的Java实现
- Java多线程-并发中的集合详解
- Java多线程中异常的处理UncaughtExceptionHandler
- struts2基于xml配置方式对Action方法进行校验
- Spring之使用JDBC访问关系数据
- 分布式环境下Spark与HDFS的配置
- struts2验证框架将验证信息输出到指定位置
- Java运行时环境初始化出现错误
- Java 中的 int 与 Integer 用于 List<Integer> 时,以及通过打印变量检測程序执行和函数调用次数计数
- java实现八皇后问题(递归和循环两种方式)
- java中String源码分析
- R.java 不能自动更新的问题