Java线程同步

2014-12-24 20:20:00 by suphy

Java线程同步

@(java)[synchronized|wait|notify|notifyAll] Author: 白万伟 Date: 2014-09-09

对象锁

对象指的是拥有synchronized修饰的函数,或者是代码块的一个类的实例.

当某个线程访问该类的方法或synchronized修饰的代码快时就要获得该对象的锁,其他线程就无法获得该对象的锁。 也就是说这个对象已经被前一个线程所占用,另外的线程无法得到该对象,所以该对象对应的方法也就无法访问,必须等到前一个线程释放对象锁才可能有机会得到对象锁。

  1. java中的每个对象都有一个锁,当访问某个对象的synchronized方法时,表示将该对象上锁,此时其他任何线程都无法在去访问该syncronized 方法了,直到之前的那个线程执行方法完毕后,其他线程才有可能去访问该synchronized方法。

  2. 如果一个对象有多个synchronized方法,某一时刻某个线程已经进入到某个synchronzed方法,那么在该方法没有执行完毕前,其他线程无法访问该对象的任何synchronzied 方法的,但可以访问非synchronzied方法。

  3. 如果synchronized方法是static的,那么当线程访问该方法时,它锁的并不是synchronized方法所在的对象,而是synchuronized方法所在对象的对应的Class对象,因为java中无论一个类有多少个对象,这些对象会对应唯一一个Class 对象,因此当线程分别访问同一个类的两个对象的static,synchronized方法时,他们的执行也是按顺序来的,也就是说一个线程先执行,一个线程后执行。

在同步方法中线程间的通信主要依靠wait() notify() notifyAll()来实现, 而且这三个方法必须在synconized代码块中使用.

wait()方法使当前线程暂停执行释放对象锁标志,让其他线程可以进入synchronized数据块,并把当前线程放入对象等待池中。 当调用notify()方法后,从对象等待池中移出任意一个线程并放到锁标志等待池中,只有锁标志等待池中的线程能够获取锁标志; 如果锁标志等待池中没有线程,则notify()不起作用。 notifyAll()则从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。

1.wait()的进一步理解:如果一个线程调用了某个对象的wait方法,那么该线程进入到该对象的等待池中(并且已经将锁释放), 如果未来的某一时刻,另外一个线程调用了相同对象的notify方法或者notifyAll方法,那么该等待池中的线程就会被唤起,然后进入到对象的锁池里面去获得该对象的锁,如果获得锁成功后那么该线程就会沿着wait方法之后的路径继续执行。注意是沿着wait方法之后.

2.notify()方法为唤醒同一个对象的锁。比如说a.notify()方法之能唤醒对应a.wait()方法调用的线程,而不能唤醒b.wait()对应的线程。 调用notify()方法并不代表释放当前对象的锁。它只是去通知其他线程进入到锁池里面去,而这个线程也不一定立即获的对象锁。


ThreadPoolExecutor运转机制详解

2014-11-22 10:48:00 by suphy

ThreadPoolExecutor运转机制详解

@(Java)[Thread|ThreadPool]

先看一下新建一个ThreadPoolExecutor的构建参数:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)

具体流程如下:

  1. 当池子大小小于corePoolSize就新建线程,并处理请求

  2. 当池子大小等于corePoolSize,把请求放入workQueue中,池子里的空闲线程就去从workQueue中取任务并处理

  3. 当workQueue放不下新入的任务时,新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize就用RejectedExecutionHandler来做拒绝处理

  4. 另外,当池子的线程数大于corePoolSize的时候,多余的线程会等待keepAliveTime长的时间,如果无请求可处理就自行销毁

内部结构如下所示:

Alt text

从中可以发现ThreadPoolExecutor就是依靠BlockingQueue的阻塞机制来维持线程池,当池子里的线程无事可干的时候就通过workQueue.take()阻塞住。

Executors类使用ExecutorService提供了一个 ThreadPoolExecutor的简单实现,但 ThreadPoolExecutor 提供的功能远不止这些 ...

read more