集成Thread类,重写run方法;实现Runnable接口,重写run方法,并把Runnable的接口实现传给Thread。
synchronized可用于方法和代码块中,在多个线程处理同一数据源时,防止出现并发问题。
public synchronized void Method1(){ ...... }
synchronized (Object o){ ...... }
该类提供了线程局部 (thread-local) 变量。访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。类似于map集合,只是这里不需要指定key值,这里的key值默认为当前线程。
ThreadLocal
threadLocal.set(new T());
T t = threadLocal.get();
Executors用于创建线程池,常用的静态方法:
newFixedThreadPool(int nThreads) | 创建固定数量的线程池 |
newCachedThreadPool() | 创建缓存的线程池 |
newSingleThreadExecutor() | 创建单个线程 |
返回值类型均为ExecutorService
ExecutorService service = Exrcutors.newFixedThreadPllo(5); 创建五个线程
service.execute(new Runnable(){...}); 执行线程任务
Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。而Callable可以返回一个结果,这个返回值可以被Future拿到,也就是说,Future可以拿到异步执行任务的返回值 .
实现Callable
ExecutorService service = Exrcutors.newSingleThreadExecutor(); 创建一个线程
Futrue
如果多个线程执行Callable任务,返回多个Future,需要借助CompletionService
ExecutorService service = Exrcutors.newFixedThreadPllo(5); 创建五个线程
CompletionService
completionService.summit(new Callable(){......}); 执行线程任务
Future
如果目前不存在这样的任务,则等待
future.get();
Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。
计算完成后只能使用 get 方法来获取结果,如有必要,计算完成前可以阻塞此方法。取消则由 cancel 方法来执行。
还提供了其他方法,以确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。
Lock功能与synchronized类似,使用简单。
Lock lock = new ReentrantLock();
lock.lock();
lock.unLock();
锁又分为读锁和写锁,读锁与读锁不互斥,读锁与写锁互斥,写锁与写锁互斥,这是由jvm自己控制的
ReadWriteLock rwk = new ReentrantReadWriteLock();
读锁:rwk.readLock().lock();
rwk.readLock().unlock();
写锁:rwk.writeLock().lock();
rwk.writeLock().unlock();
Conditon可以用来替换传统的wait() 和 notify() 方法;
Condition必须和Lock一起使用,没有Lock就没法使用Condition.
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
lock.lock(); ...... condition.await(); ......condition.signal();//唤醒某一个线程
Semaphore通常用于限制访问某些资源的线程数,但是并未实现线程同步问题。常用方法acquire、release,用户获取和释放线程资源。
ExecutorService service = Executors.newCachedThreadPool();//使用并发库,创建缓存的线程池
Semaphore sp = new Semaphore(3);//创建一个Semaphore信号量,并设置最大并发数为3
new Thread(new Runnable() {
public void run(){ .... sp.acquire(); ...... sp.release()});
CyclicBarrier可以使不同的线程彼此等待,等这些不同的线程都执行完了,再执行下面的程序。一般用于主任务执行需要所有的子任务执行完毕的功能需求中。
ExecutorService service = Executors.newCachedThreadPool();
CyclicBarrier cb = new CyclicBarrier(2);//设置2个等待线程,2个线程都执行完,再执行后面的程序。
new Runnable(){
public void run(){ runnable1; cb.await(); runnable2; cb.await(); };
11.Exchanger线程同步工具
Exchanger只能用于两个线程之间交换数据,如果是多个线程运行,一次也只能在两个线程间交换数据。
只有当每个线程都在进入 exchange ()方法并给出对象时,才能接受其他线程返回时给出的对象。