一 创建线程的传统方式
1 在Thread子类覆盖run方法
2 实现Runnable,重写run方法,传递给Thread
二 传统定时器
Timer类和TimerTask配合使用
三 线程同步互斥与通信
1 使用synchronized代码块或synchronized方法
2 wait与notify实现线程间通信
synchronized (object){
object.wait();//当前线程进入wait set(可理解为线程休息室),等待再次获取对象锁
}
object.notify()//从wait set抓出一个线程,被唤醒的线程就推出wait set,被抓出的线程等待获取object对象锁,获取成功后继续后续执行
四 ThreadLocal线程范围的共享变量
ThreadLocal 的set方法设置变量 ,内部存储值的是一个ThreadLocalMap的key value数据结构,key为当前线程ThreadLocal,ThreadLocalMap是Thread内部属性threadLocals
五 Java线程并发
ExecutorService threadPool = Executors.newFixedThreadPool(n)//创建n个线程
ExecutorService threadPool = Executors.newCachedThreadPool()//创建缓存线程池
ExecutorService threadPool = Executors.newSingleThreadExecutor()//单线程池创建
六 Callable与Future的应
Feture取得的结果类型和Callable返回的结果类型必须一致,这是通过泛型来实现的
Callable要采用ExecutorService的submit方法提交,返回的Feture对象可以取消任务
单任务结果等待:
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future<String> future = threadPool.submit(new Callable<String>() {public String call() throws Exception {});
多任务结果等待:
CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool2);
completionService.take().get()//将等待completionService所有submit提交的内容执行完了统一返回结果
七 Lock与Condition线程锁技术
Lock比synchronized更加面向对象,与生活中的锁类似。
读写锁:分为读锁与写锁,多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥,这是由jvm自己控制的。例:ReentrantReadWriteLock
Condition的功能类似在传统线程技术中的Object wait和notify的功能,在等待Condition时,允许发生"虚假唤醒"
八 Semaphore信号灯
Semaphore可以维护当前访问自身对象的线程个数,并提供同步机制。使用Semaphore可以控制同时访问资源的线程数。
Semaphore sp = new Semaphore(n)
sp.acquire();//申请一个许可,当sp.availablePermits()>0时,申请成功,反之等待许可的释放
sp.release();//释放一个许可,将其返回给信号量。
九 CyclicBarrier屏障
一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
例如:CyclicBarrier cb = new CyclicBarrier(3);表示在cb.await();这里需要等待3个线程的共同到达,才能继续进入下一步
十 CountDownLatch
一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待
例如:CountDownLatch studentLatch= new CountDownLatch(1)
Runnable runnable = new Runnable() {
public void run() {
try {
System.out.println("线程" + Thread.currentThread().getName() + "已经到达集合点");
studentLatch.await();//等待countdown计数为0
System.out.println("线程" + Thread.currentThread().getName() + "上车");
} catch (Exception e) {
e.printStackTrace();
}
}
};
service.execute(runnable);
Thread.sleep(15000);
studentLatch.countDown() ;//时间到,递减锁存器的计数,如果计数到达零,则释放所有等待的线程。
十一 Exchange线程间数据交换
其中一个线程先拿出数据等待第二个线程拿出数据才能彼此交换
String data2 = (String)exchanger.exchange(data1);//线程一
String data2 = (String)exchanger.exchange(data1);//线程二
十二 可阻塞的队列BlockQueue
队列包含固定长度队列和不固定长度的队列
ArrayBlockingQueue:固定长度不变的队列
只有put方法和take方法才具有阻塞功能,内部实现采用的Lock锁
十三 同步集合
java.util.concurrent包下:
ConcurretHashMap、CopyOnWriteArrayList、CopyOnWriteArraySet
SynchronousQueue:一种阻塞队列,其中每个插入操作必须等待另一个线程的对应移除操作 ,反之亦然