您的位置:首页 > 编程语言 > Java开发

Java核心编程九:线程与进程处理

2013-12-23 18:20 393 查看
1 线程

Thread类:
Thread(Runnable task)
void start()
void stop() 不建议使用
static void sleep(ms) 当抛出异常时,中断位置也随着清除

Runnable接口
void run()

2 中断线程
除了stop()方法之外,可以使用interrupt方法来终止一个线程。当向一个线程发送中断信号时,线程的中断状态位将被设置。我们需要时刻检查线程的中断位置是否被设置,以退出线程。
如果线程处理阻塞中,则没有办法执行用户的检查状态代码,但此时会抛出中断异常,供我们捕获以处理阻塞状态下的中断。
void interrupt() 向线程发送一个中断请求,若当前线程处于阻塞调用中,则抛出中断异常
static bool interrupted() 检查当前线程是否被中断,并清除中断状态
bool isInterrupted() 只检查当前线程的中断状态
static Thread currentThread() 返回当前线程的执行对象。
3 线程状态





isAlive() 如果是可运行和阻塞的返回TRUE,否则返回FALSE
suspend()/resume() 挂起及恢复线程
join() 供主线程调用,一直等待子线程终止。
4 线程属性
4.1 线程优先级
Java线程均有自己的优先级,默认情况下继承其父线程的优先级。可以对线程的优先级进行调整。但不同平台上JVM实现不同,因此不要将正确性建立在优先级调度的假设上。
void setPriority(int) 设置新的优先级
static int MIN_PRIORITY(1) NORMAIL_PRIORITY(5) MAX_PRIORITY(10)
static void yield() 主动让出CPU执行资源
4.2 守护线程
可以将线程设置为守护线程,其没有什么特殊的地方。
setDaemon(true)
4.3 线程组
线程组提供了给一组线程命名和统一操作的能力。
Thread类:
Thread(ThreadGroup g,String name) 将线程加入到线程组中
ThreadGroup getThreadGroup() 获取当前线程的线程组
ThreadGroup类
ThreadGroup(String name)
ThreadGroup(ThreadGroup parent,String name)
int activeCount() 获取当前线程组中的活跃线程数
int enumerate(Thread[] list) 将线程组中的线程放到数据组中
ThreadGroup getParent() 获取父线程组
void interrupt() 中断此线程组的所有线程
5 同步
5.1 锁对象
在util.concurrent.locks包下定义了锁的接口和实现。
Lock接口
void lock()
void unlock()
bool tryLock()
Condition newCondition() 基于锁返回一个条件变量

ReentrantLock类
可重入的锁,实现了Lock的接口。线程在持有之后可以重复加锁,锁对象维护一个持有计数来追踪对lock()方法的嵌套调用。

ReadWriteLock()接口
Lock readLock() 返回一个读锁,当需要读锁定时,使用返回锁的lock()方法
Lock writeLock() 返回一个写锁,当需要写锁定时,使用返回锁的lock()方法

ReentrantReadWriteLock类
读写锁实现

5.2 条件变量
当一个线程拿到锁进行临界区,如果发现它必须等待特定条件满足才能执行。这时候就需要条件变量来管理这种情况。此时其他线程必须生成相应的条件,并通过signalAll()或signal()来通知被阻塞的线程,以继续其执行。
locks.Condition类
void await() 在条件变量上等待,也可设置超时。如果其间被中断,则抛出中断异常
void awaitUninterruptibly() 在条件变量上等待,但不受中断影响
void signalAll() 通知所有等待在条件变量上的线程,由其竞争产生后续执行者
void signal() 随机通知一个可执行线程。

5.3 Synchronized关键字
在jdk5之前,Java中并没有显式的锁。但每个Java对象都有一个隐式的锁。如果一个方法声明了Synchronizated关键字,那么对象的锁就将整个方法保护起来。
隐式的对象只能有一个关联条件变量。在其上可以调用wait()和notifyAll()。
这种方式来写代码,会更简洁。但也其局限。比如,不能中断等待锁的线程,不能设置阻塞等待超时等。
建议通常使用util.concurrent包中提供了机制,而不是显式的使用Lock和Synchronized方式。只有在非常需要Lock的时候才使用它。
Sync机制是实现的Object基类中的:
void notifyAll()
void notify()
void wait()
void wait(ms,nanos)
为了提升效率,可以在方法内部实现同步块
synchronized(obj)
{
critical section

}
5.4 volatile
volatile关键字为对单个实例域的同步访问提供了一个无锁机制。

5.5 tryLock
tryLock以非阻塞的方式去尝试获取一个锁。如果锁被其他线程占用,则立即返回false。当然也可以设置超时时间。
如果调用lock方法时线程被阻塞,此时线程收到中断,则中断线程仍将被阻塞,直到获得锁,此时如果死锁,线程将无法被中断。而在调用tryLock()方法时,在等待时被中断,则会抛出中断异常。

5.6 废弃的stop与suspend方法
stop和suspend都采用了比较粗暴的方式对线程进行中止和挂起,此时可能导致线程正在更新的对象不完整,或者持有锁被挂起。会产生一些不可预料的问题,因此不建议使用这两个方法。而是采用中断的方式,由线程自己去处理是否需要退出。

6 阻塞队列
在util.concurrent包里定义了一系列的阻塞队列,其都实现了BlockingQueue<T>接口,可以方便用来实现生产者和消费者线程的互操作,而不使用显式的同步机制。
ArrayBlockingQueue 需要给定容量,支持公平性
LinkedBlockingQueue 容量无上限
ProorityBlockingQueue 元素按优先级顺序被移除
DelayQueue 返回指定了延迟已过通过的对象
其都实现了BlockingQueue<T>接口,此接口有以下方法:
void put(T elemnt) 添加元素,必要时阻塞
T take() 移除元素,必要时阻塞

offer() 添加元素,若满返回false
poll() 提取并移除元素,若空返回false
peek() 提取元素,若空返回false

add 添加元素,若满抛出异常
remove 提取并移除元素,若空抛出异常
element 提取元素,若空抛出异常

7 线程安全集合
7.1 并发集合
util.concurrent包提供了线程安全的容器实现,如ConcurrentLinkedQueue和ConcurrentHashMap。这些集合使用了复杂的算法,所以不会锁住整张表。这些集合返回弱一致性的迭代器,这意味着迭代器不一定反映出当前的修改,但它不会抛出任何异常。
ConcurrentHashMap<K,V>类
V putIfAbsent(K key,V val) 若K不存在则插入,并返回NULL,否则返回K已关联的值。
bool remove(K key,V val) 若K存在,则移除之,否则返回FALSE
bool replace(K key,V oldval,V newval) 若K与old关联,则更新之,否则返回false
7.2 写时拷贝数组
CopyOnWriteArrayList和CopyOnArraySet也是线程安全的集合,其中所有对它们修改的线程都会拥有一份数据的复本。所以旧的迭代器会访问到旧的数据,而且并发也不需要同步开销。
7.3 同步包装器
旧的容器与Vector和Hashtable类就分别提供了线程安全的实现。但后续已经弃用。而新加的ArrayList和HashMap则不是线程安全的。这些集合可以使用同步包装器变成线程安全的。
List lst = Collections.synchronizedList(new ArrayList());
Map map = Collections.synchronizedMap(new HashMap());

8 Callable

Runnable封装一个异步执行的任务,它没有参数和返回值。Callable与之相似,但它有返回值。
public interface Callable<T>
{
T call() throws Excepion;

}

9 Future
Feture可以保存了异步计算的结果,它同时也关联着执行任务相关状态,我们可以通过它来封装异步执行的任务。

为了简化使用,FetureTask<T>包装器实现了Runuable和Feture的接口,可以方便的包装Runnable和Callable对象,并保存其执行结果。
Feture<T>的接口如下:

V get() 获取结果,如果没有结果可用,则阻塞;也可以设置超时,这样则阻塞到超时。
bool cancel() 取消任务
bool isCancelled()判断是否任务完成前被取消了。
bool isdone() 返回任务是否完成,完成后被中断或异常也会返回true.

9 执行器
Executors类提供了一系统创建线程池的方法,可以创建不同类型的线程池,以避免创建大量的线程。
9.1 线程池
ExecutorService newCachedThreadPool()
用于创建一个线程池,对于新的请求,若有空闲线程则执行之,否则新建线程。
ExecutorService newFixedThreadPool()
创建固定大小的线程池,对于新请求,即使无空闲线程也不创建,等待已有线程处理
ExecutorService newSingleThreadExecutor()
创建大小为1的线程池

ExecutorService定义了线程池的接口
Future<?> submit(Runnable task)
Future<T> submit(Callable<T> task)
向线程池提交任务,并返回Future对象,供后续查询其执行状态。
void shutdown() 当任务执行结束后,关闭线程池

9.2 定时执行
ScheduledExecutorService newSingleThreadScheduledExecutor()
创建定时执行的单个线程池
ScheduledExecutorService newScheduledThreadPool()
创建定时执行的线程池

随后可以设置定时执行的时间和频率
ScheduledFutue<T> schedule(Callable<T> task,long time,TimeUnit unit)
ScheduledFutue<T> schedule(Runnable task,long time,TimeUnit unit)
ScheduledFutue<T> scheduleAtFixedRate(Runnable task,long delay,long period,TimeUnit unit)

10 同步器
concurrent包中,包含了若干同步的原语,以方便线程间协作。

CyclicBarrier 在内存中设置个屏障,当所有线程到达后才继续向下执行
CyclicBarrier(int nthread,Runnable task) 创建器,设置了所有线程到达后的执行动作。
await() 完成的线程需要在栅障上等待

CountDownLatch 令一个线程集等待直到计数器变为0为止
CountDownLatch(int n)
void await() 等待倒计时完成

Exchanger 支持两个线程在同个数据缓冲区上交换数据
生产者可以生产数据,当缓冲区满,调用exchange,等待消费者调用exchange来交换数据。这里要求二线程都必须提供两个缓冲区实例。
T exchange(T item,long time,TimeUnit unit)

SynchronousQueue 支持单个元素交换的同步阻塞队列
void put(T item)
T take()

Semaphore 信号量
void acquire()
bool tryAcquire()
void release()

11 进程
在java.lang包中提供了进程,以及通过进程执行外部命令的一些类。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: