---------------------- android培训、java培训、期待与您交流! ----------------------
5.多个线程访问共享对象和数据的方式
如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable
对象中有那个共享数据。
如果每个线程执行的代码不同,这时候需要用不同的Runnable对象,这时可以将共
享数据封装在另外一个对象中,然后将这个对象逐一传递给各个Runnable对象。每
个线程对共享数据的操作方法也分配到那个对象身上去完成(把数据和数据操作封装
在一起),这样容易实现针对该数据进行的各个操作的互斥和通信。
多个线程访问共享对象和数据时,数据容易出现安全问题,因此,要注意加锁。
6.线程池的概念:首先创建一些线程,它们的集合称为线程池,当服务器接受到一个客户请求后,就从线程池中取出一个空闲的线程为之服务,服务完后不关闭该线程,而是将该线程还回到线程池中。
在线程池的编程模式下,任务是提交给整个线程池,而不是直接交给某个线程,线程池在拿到任务后,它就在内部找有无空闲的线程,再把任务交给内部某个空闲的线程,若无空闲线程,则任务处于等待状态。记住,任务是提交给整个线程池,一个线程同时只能执行一个任务,但可以同时向一个线程池提交多个任务。
Executors工厂类才产生线程池,相关方法(部分)如下:
static ExecutorService newCachedThreadPool()
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。
static ExecutorService newFixedThreadPool(int nThreads)
创建一个可重用固定线程数的线程池。
static ScheduledExecutorServicenewScheduledThreadPool(int nThreads)
创建一个可重用固定线程数的线程池,它可安排在给定延迟后运行或者定期地执行。
static ExecutorService newSingleThreadExecutor()
创建一个只有一个线程的线程池,相当于newFixedThreadPool(1)
static ScheduledExecutorServicenewSingleThreadScheduledExecutor()
创建一个单线程的线程池,它可安排在给定延迟后运行或者定期地执行。
ExecutorService 常用方法:
void execute(Runnable command) 执行给定的命令,此方法从父接口Executor中继承而来。
void shutdown()
执行以前提交的任务,但不接受新任务,任务执行完成后池中所有的线程都将死亡。
List<Runnable> shutdownNow() 试图停止所有正在执行的活动任务,暂停处理
正在等待的任务,并返回等待执行的任务列表。
<T> Future<T> submit(Callable<T> task)
提交一个返回值的任务用于执行,返回一个表示任务的结果的Future。
Future<?> submit(Runnable task) 提交一个 Runnable 任务用于执行,并返回一个
表示该任务的 Future。Future无意义 。
Future类中常用方法:
V get() 等待计算完成,然后获取其结果。
V get(long timeout, TimeUnit unit)
最多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)。
boolean isCancelled() 如果在任务正常完成前将其取消,则返回 true。
boolean isDone() 如果任务已完成,则返回 true。
ScheduledExecutorService类继承了ExecutorService接口,常用方法有:
<V> ScheduledFuture<V> schedule(Callable<V> callable, longdelay, TimeUnit unit)
创建并执行在给定延迟后启用的ScheduledFuture。
ScheduledFuture<?> schedule(Runnable command,long delay, TimeUnit unit)
创建并执行在给定延迟后启用的一次性操作。
ScheduledFuture<?> scheduleAtFixedRate(Runnablecommand, long initialDelay, long period, TimeUnit unit)
创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推。
ScheduledFuture<?> scheduleWithFixedDelay(Runnablecommand, long initialDelay, long delay, TimeUnit unit)
创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。
示例:
public class TreadPoolTest {
public static void main(String[] args) {
//ExecutorServicepool=Executors.newFixedThreadPool(3);
//ExecutorServicepool=Executors.newCachedThreadPool();
ExecutorServicepool=Executors.newSingleThreadExecutor();
for(int i=0;i<10;i++){
final int a=i;
pool.execute(new Runnable() {
public void run() {
for(int j=0;j<5;j++){
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace(); }
System.out.println("thread:"+a+" loop:"+j);}}});}
Future<String>fut=pool.submit(new Callable<String>() {
public String call()throws Exception {
System.out.println("call is running……");
return "hello,java";}});
System.out.println(fut.get());}}
7.CompletionService用于提交一组Callable任务,其take方法返回任务中已完成的一个Callable任务对应的Future对象。
示例:
ExecutorService service= Executors.newFixedThreadPool(3);
CompletionService<Integer>completionService =
new ExecutorCompletionService<Integer>(service);
for (int i = 0; i < 20; i++) {
completionService.submit(new Callable<Integer>(){
public Integer call()throws Exception {
Integer a = 0;
try {
a = new Random().nextInt(10);
System.out.println("product a:" + a);
Thread.sleep((long) (a * 100));
} catch (Exception e) {
}
return a;
}
});
}
for (int i = 0; i < 20; i++) {
Future<Integer> f = completionService.take();
System.out.println("get a:" + f.get());
}
以上代码基本上遵循返回一个数,得到一个数的趋势。
8.读写锁:
示例:
public class LockTest {
static Source source=new Source();
public static void main(String []a){
for(int i=0;i<4;i++){
new Thread(new Runnable() {
public void run() {
source.setA();}}).start();
new Thread(new Runnable() {
public void run() {
source.getA();}}).start();}}}
class Source{
int a=0;
ReadWriteLock rwl=new ReentrantReadWriteLock();
void setA(){
rwl.writeLock().lock();
System.out.println(Thread.currentThread().getName()+
" 准备产生a……");
try {
Thread.currentThread().sleep(1000);
} catch (Exception e) {
e.printStackTrace();}
a=new Random().nextInt();
System.out.println(a);
System.out.println("已经产生a");
rwl.writeLock().unlock();}
void getA(){
rwl.readLock().lock();
System.out.println(Thread.currentThread().getName()+
" 准备得到a……");
try {
Thread.currentThread().sleep(1000);
} catch (Exception e) {
e.printStackTrace();}
System.out.println(a);
System.out.println("已经得到a");
rwl.readLock().unlock();}}
通常在释放锁时,代码放在finally中,避免抛出异常时,锁为释放资源。
读写锁应用之缓存系统:
public class CacheDemo {
privateMap<String, Object> cache = new HashMap<String, Object>();
public staticvoid main(String[] args) { }
privateReadWriteLock rwl = new ReentrantReadWriteLock();
public Object getData(String key){
rwl.readLock().lock();
Object value = null;
try{
value= cache.get(key);
if(value== null){
rwl.readLock().unlock();
rwl.writeLock().lock();
try{
if(value==null){
value = "aaaa";//实际是去queryDB();
}
}finally{
rwl.writeLock().unlock();
}
rwl.readLock().lock();
}
}finally{
rwl.readLock().unlock();
}
return value;
}
}
---------------------- android培训、java培训、期待与您交流! ----------------------