JAVA并发编程知识要点
JAVA多线程
多线程和多进程
多线程共享数据更为方便,容易管理,容易切换。
多线程仍然属于一个程序。
Thread.sleep()使当前进程休眠,毫秒为单位。
多线程允许多个代码同时运行。
多线程的实现
继承Java.lang.Thread类,实现run方法
实现java.lang.Runnable接口,实现run方法
启动:start方法,会以新进程的方式调用run方法
直接调用run方法退化为串行执行
Run方法结束后线程自动结束
所有线程都终止程序才会终止
实现runnable的类必须依赖于thread才能启动
即new Thread(new Thread2()).start();
Main函数可以先于其他进程结束
Thread.currentThread.getname()可以查看当前线程的名称
一个线程多次start,要并行执行需要再new一个出来
Thread占据了父类的名额,不如runnable方便,并且不容易实现资源共享
Thread类也实现的Runnable接口
建议使用runnable接口。以便于继承其他类
多线程信息共享
线程之间没有交流->粗粒度
线程之间有信息通信,通过共享变量->细粒度
Static或者runnable类的成员变量可以共享
Thread类仅能通过static来共享变量。
Runnable类可以通过普通成员变量来共享。
这种方法的信息共享不是完全实时的。原因有两点:工作缓存副本、缺乏加锁限制
解决方法:加volatile修饰->解决工作缓存副本问题
互斥:Synchronized代码块或者函数,只允许一个进程进入->解决加锁限制。
括号中的是任意一个非空的对象。进程抢str的锁,如果抢到则可以进入。
修饰函数的情况。
Java多线程管理
线程的状态: new runnable running block terminated
Runnable 和 running状态在CPU指导下来回切换
Sleep->时间一到,自己会醒来
Wait/notify/notifyAll ->等待,需要别人唤醒(直接使用,例如wait(); notifyAll();
Join->等待另一个线程结束
Interrupt->发送中断信号。线程中需要用interrupted()方法来测试是否收到过interrupt信号。
上述方法中进程被动暂停和终止,不利于资源释放
解决办法:定期监测共享变量
多线程死锁->将资源进行等级排序,防止交叉调用。
Jvisualvm可以查看线程的当前信息。
守护线程->run方法结束或者Main函数结束都可以触发守护线程的结束。和main函数心连心。守护进程不要访问资源。
Executor框架
并行模式:主从模式,Worker模式
分离任务的创建和执行者的创建
程序员无需关心线程池执行任务过程
Callable接口和runnable类相似
定义线程池
ThreadPoolExecutor executor =(ThreadPoolExecutor)Executors.newCachedThreadPool();
Executor.execute(task);
Task要实现runnable接口。
指定线程池的容量:
Call()函数可以有返回值
执行executor.submit(task)时可以用一个future对象来接收作为返回值。如果任务结束可以通过future的get方法得到结果
Fork-join 框架
ForkJoinPool pool = new ForkJoinPool(4)//四线程的线程池
继承自RecursiveTask的任务,实现compute方法
并发数据结构
常用的数据结构是线程不安全的。
通过collections.synchronizedXXX()包裹以后可以将数据结构变成同步安全的
(Deque是双向的队列)
Thread类的构造方法可以指定线程名字。例如
并发协作控制
Lock可以实现同步的效果
分离读写操作,tryLock判断锁是否空闲
相关类:ReentrantLock, ReentrantReadWriteLock
函数:lock, unlock
用匿名类创建线程(直接实现runnable接口)
tryLock()函数在资源被占用时立即返回false。没有占用的时候就实现上锁功能。此函数不阻塞,但是lock()函数是阻塞的。
Unlock()函数可以释放资源。
Semaphore可以控制多个同时访问
Latch 等待锁 用来同步执行任务的一个或者多个进程
具体类是CountDownLatch: countdown() await()
Countdown()函数表示将latch减一,当latch等于0时会唤起所有因为await()而阻塞的线程。
Barrier集合点
具体类是CyclicBarrier,构造函数给定要同步的线程数量,await()等待其他线程,到达数量以后就放行。
这句话代表有3个完成以后,自动执行finalResultCalculator中的run方法。
Phaser :阶段结束以后进行同步。
常用方法 arrive(), arriveAndAwaitAdvance()
Exchanger:允许在并发线程中互相交换消息
常用方法:exchange().进程双方同时到达exchange函数位置时完成数据的交换。
交换是双向的。
定时任务执行:
TimerTask和Timer类实现定时机制