Java并发总结

来源:互联网 发布:mac的usb配件已停用 编辑:程序博客网 时间:2024/06/01 07:37

线程池

ExecutorService es = Executors.newCachedThreadPool();
ExecutorService es = Executors.newFixedThreadPool();
es.execute();
Future f = es.submit()

Thead.yield()

Thead.yield()暗示当前线程工作做得差不多了,可以讲CPU让给其他线程。不过这只是一种暗示,具体操作还要看处理机,不要太过依赖这个方法。

new Thread().setDaemon()

线程设置为后台线程,后台线程创建的线程都是后台线程。后台进程终止后会终止他创建的非后台线程,而此时非后台线程待执行的finally代码块不会执行

new Thread().join()

执行暂停主线程的执行,并在当前子线程执行完后或者调用interrupt()方法主动中断线程,主线程才继续执行。

设置线程异常回调

Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler())
new Thread().setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

可以实现试图获取锁,如果指定时间没有获取锁则走其他逻辑流程,而synchronized做不到
ReentrantLock lock = new ReentrantLock();
lock.lock();
lock.unlock()

CAS实现,原子类

java.util.concurrent.atomic类实现了CAS(原理是乐观锁),具有原子性

ThreadLocal

线程本地存储

线程状态

1.新建
2.就绪
3.阻塞
4.死亡

中断

new Thread().interrupt()设置一个标记,表面这个线程可以中断,new Thread().interrupted()读取中断标记判断是否可以中断,读取后中断标记会被清除。我们可以读取中断标记,以判断是否调用new Thread().stop()终止线程。new Thread().stop()会立即停止线程。或其他方式终止线程。new Thread().stop()不建议使用。

new Object().wait()和new Object().notify(),new Object().notifyAll()

new Object().wait():线程等待
new Object().notify():通知一个在new Object()对象上等待的线程
notifyAll():通知所有在new Object()对象上等待的线程
错失的信号
意思是当线程1判断等待的条件成立后,在即将调用wait时,另一个协作线程2调用了notify并改变等待条件,这时等待条件已经改变,而线程1因为已经判断过等待条件而直接进入等待,而线程2却已经调用notify并改变等待条件不会再被调用一次,故线程1将一直等待下去。解决办法是,让等待的条件判断和wait的调用放在同一个同步代码块里,使其具有原子性。

生产者消费者与队列

java.util.concurrent. BlockingQueue是特殊的队列,他的两个方法put和take与普通队列不同。
Put:将指定元素插入此队列中,将等待可用的空间(如果有必要),如果没有可用空间则一直等待。
Take:获取并移除此队列的头部,在元素变得可用之前一直等待(如果有必要)。
这样的话就可以优雅的实现多线程的生产者与消费者问题。
BlockingQueue是一个接口,其子类LinkedBlockingQueue是一个无界队列,ArrayBlockingQueue是一个有固定尺寸的队列。

PipedWriter和PipedReader

同步辅助类

CountDownLatch

有时候会有这样的需求,多个线程同时工作,然后其中几个可以随意并发执行,但有一个线程需要等其他线程工作结束后,才能开始。举个例子,开启多个线程分块下载一个大文件,每个线程只下载固定的一截,最后由另外一个线程来拼接所有的分段,那么这时候我们可以考虑使用CountDownLatch来控制并发。
CountDownLatch是JAVA提供在java.util.concurrent包下的一个辅助类,可以把它看成是一个计数器,其内部维护着一个count计数,只不过对这个计数器的操作都是原子操作,同时只能有一个线程去操作这个计数器,CountDownLatch通过构造函数传入一个初始计数值,调用者可以通过调用CounDownLatch对象的cutDown()方法,来使计数减1;如果调用对象上的await()方法,那么调用者就会一直阻塞在这里,直到别人通过cutDown方法,将计数减到0,才可以继续执行。

CyclicBarrier

构造方法指定一个参与者数量N,和一个回调Runnable方法,在所有参与者都已经在此barrier上调用await方法之前,将一直等待,在所有参与这都调用了wait后会调用回调Runnable方法,然后释放所有线程让线程解除阻塞。

DelayQueue

元素是实现了Delayed接口的对象,对象里可以指定延迟时间,到达延迟时间的元素才能通过take方法获得时间最近的元素并删除元素,如果没有到达延迟时间的元素,则一直等待。
PriorityBlockingQueue:也是一种队列,这种队列可以通过排序器进行自定义排序,来达到按照不同顺序弹出元素的目的。

ScheduledThreadPoolExecutor

定时执行任务。

Semaphore

Semaphore semp = new Semaphore(5);
semp.acquire();
//业务逻辑
emp.release();
这里设置五个信号,调用acquire()的方法表示获取一个信号,获取信号后才能继续执行否则阻塞等待,acquire()方法释放型号。

Exchanger

线程间交换数据。

将非同步集合变为同步集合

利用java.util.Collections类的synchronizedList,synchronizedMap,synchronizedSet等方法。

CopyOnWriteArrayList,CopyOnWriteArraySet

ConcurrentHashMap,ConcurrentLinkedQueue。
允许并发读写

读写锁

获取写锁后,就不能获取读锁了。只有当释放写锁后才能获取读锁。写锁只有一把,读锁有多把。所以在读的地方设置获取读锁,写的地方设置获取写锁。这样写的时候就不能读,读的时候就就不能写。